ARM 组装难题

发布于 2024-09-04 03:44:07 字数 208 浏览 3 评论 0原文

首先,我不确定是否存在解决方案。我花了几个多小时试图想出一个,所以要小心。

问题:

r1 包含任意整数,标志根据其值设置。如果 r1 为 0x80000000,则将 r0 设置为 1,否则设置为 0,仅使用两条指令。

用 3 条指令很容易做到这一点(有很多方法),但是用 2 条指令做到这一点似乎非常困难,而且很可能是不可能的。

First of all, I'm not sure if solution even exists. I spent more than a couple of hours trying to come up with one, so beware.

The problem:

r1 contains an arbitrary integer, flags are not set according to its value. Set r0 to 1 if r1 is 0x80000000, to 0 otherwise, using only two instructions.

It's easy to do that in 3 instructions (there are many ways), however doing it in 2 seems very hard, and may very well be impossible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

云之铃。 2024-09-11 03:44:08

这是一个部分解决方案,它在 r0 的最高位给出了正确的答案,因此它可用作移位操作数 (r0 lsr #31)。

; r0 = r1 & -r1
rsb r0, r1, #0
and r0, r0, r1

这是有效的,因为 00x80000000 是唯一在求反时保留其符号位的数字。我相当确定精确的解决方案是不可能的。

编辑:不,这并非不可能。请参阅马丁的回答。

Here's a partial solution that gives the correct answer in the top bit of r0, so it is available as a shifter operand (r0 lsr #31).

; r0 = r1 & -r1
rsb r0, r1, #0
and r0, r0, r1

This works because 0 and 0x80000000 are the only numbers that retain their sign bits when negated. I'm fairly sure an exact solution is impossible.

EDIT: no, it's not impossible. See Martin's answer.

情未る 2024-09-11 03:44:08
adds  r0, r1, #0x80000000 ; if r1 is 0x80000000, r0 will now hold 0
movne r0, #1              ; otherwise, set r0 to 1

这相当于:

unsigned int r0, r1;
r0 = r1 + 0x80000000; // 32 bits, so top bit will be lost on overflow
if (r0 != 0)
{
    r0 = 1;
}
adds  r0, r1, #0x80000000 ; if r1 is 0x80000000, r0 will now hold 0
movne r0, #1              ; otherwise, set r0 to 1

This is equivalent to:

unsigned int r0, r1;
r0 = r1 + 0x80000000; // 32 bits, so top bit will be lost on overflow
if (r0 != 0)
{
    r0 = 1;
}
著墨染雨君画夕 2024-09-11 03:44:08

类似于:

mov r0,r1,lsr #31

Something like:

mov r0,r1,lsr #31

风柔一江水 2024-09-11 03:44:08

如果想使用“快速”指令,这是一个难题。我不太能想出一个解决方案,但可以提供更多“想法”:

; If goal were to have value of zero if $80000000 and something else otherwise:
  adds r0,r1,r1 ; Overflow only if $80000000
  movvc r0,#whatever

; If goal were to have value of $80000000 if $80000000 and zero otherwise
  subs r0,r1,#0  ; Overflow only if $80000000
  movvc r0,#0 ; Or whatever

; If the goal were to have value of $7FFFFFFF if $80000000 and zero otherwise
  adds r0,r1,r1,asr #31 ; Overflow only if $80000000
  movvc r0,#0

; If carry were known to be set beforehand
  addcs r0,r1,r1 ; Overflow only if $80000000 (value is 1)
  movvc r0,#0

; If register r2 were known to hold #1
  adds r0,r1,r1,asr #31
  ; If $80000000, MSB and carry set
  sbc r0,r2,r0,lsr #31

这些都不是完美的解决方案,但它们很有趣。

Tough puzzle if one wants to use "fast" instructions. I can't quite come up with a solution, but can offer a couple more 'notions':

; If goal were to have value of zero if $80000000 and something else otherwise:
  adds r0,r1,r1 ; Overflow only if $80000000
  movvc r0,#whatever

; If goal were to have value of $80000000 if $80000000 and zero otherwise
  subs r0,r1,#0  ; Overflow only if $80000000
  movvc r0,#0 ; Or whatever

; If the goal were to have value of $7FFFFFFF if $80000000 and zero otherwise
  adds r0,r1,r1,asr #31 ; Overflow only if $80000000
  movvc r0,#0

; If carry were known to be set beforehand
  addcs r0,r1,r1 ; Overflow only if $80000000 (value is 1)
  movvc r0,#0

; If register r2 were known to hold #1
  adds r0,r1,r1,asr #31
  ; If $80000000, MSB and carry set
  sbc r0,r2,r0,lsr #31

None of those is a perfect solution, but they're interesting.

难如初 2024-09-11 03:44:07

类似的东西

SMMUL r0,r1,r1
MOV r0,r0,lsr #30

something like

SMMUL r0,r1,r1
MOV r0,r0,lsr #30
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文