【问题标题】:ARM assembly puzzleARM 组装拼图
【发布时间】:2010-06-02 18:46:40
【问题描述】:

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

问题:

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

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

【问题讨论】:

  • 架构版本有限制吗?这可能会影响是否有解决方案。
  • 现在对我来说更多的是一个好奇的问题,而不是实际应用,所以任何拱门都可以
  • 过去一天想了很多,我相信这是不可能的。有很多方法可以在 3 条指令中到达那里,但正如所问的,我想不出在 2 条指令中实现它的方法。

标签: assembly arm bit-manipulation puzzle


【解决方案1】:

类似

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

【讨论】:

  • 不错的答案,SMMUL 有四个操作数,是吗?可能是 SMMUL r2,r0,r1,r1。我认为如果设置了 r1 的 msbit,r0 最终会是 1,2 或 3。
  • Arm 的文档将 SMMUL 描述为有符号顶字乘法,因此它被列为 3 寄存器操作码。我的想法是:0x80000000 x 0x80000000。在顶部字中给出 0x40000000,因此 30 位移位会将 bit30 带到 bit0。 (这里没有要测试的 arm V6 架构)
  • @dwelch:你在想 SMULL。 SMMUL 是一个 ARMv6 指令,只给出结果的前 32 位。
  • 谢谢,很高兴知道。无论哪种方式,结果的高两位可以是 1、2 或 3,具体取决于 r1 中的其他位,您仍然需要第三条指令来将这些低两位组合在一起以获得结果。
  • @dwelch:对有符号数求平方的最大结果是 (-2^31)^2 = 2^62; 0x80000000 以外的任何值都会给出更小的(非负数)结果。在您的 4 位示例中,您正在执行无符号乘法;有符号乘法会将 0xF 解释为 -1,结果为 0x01。所以这两条指令确实给出了正确的结果,不需要第三条。
【解决方案2】:

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

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

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

编辑:不,这不是不可能的。见马丁的回答。

【讨论】:

  • 否定的好把戏。不幸的是,提取最高位需要第三条指令(或修改使用结果的指令,这并不总是可能的)。
  • 我整天都在想这个问题,我敢肯定两个指令的解决方案也是不可能的。
【解决方案3】:
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;
}

【讨论】:

  • 您反转了结果:当 r1==0x80000000 时,问题规范要求 r0 中为 1,否则为 0,并且您在 r1==0x80000000 上将 r0 设置为 0,否则设置为 1,这是一个更简单的问题(这是在 3 条指令中完成工作的方法之一)。
【解决方案4】:

类似:

mov r0,r1,lsr #31

【讨论】:

  • 只要设置了 r1 的高位,就会将 r0 设置为 1。这不是 OP 所要求的。
  • 啊,我看到我看到的是位而不是值
【解决方案5】:

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

;如果目标值为零,如果 $80000000 或其他值: 添加 r0,r1,r1 ;仅在 $80000000 时溢出 movvc r0,#随便 ;如果目标的价值为 80000000 美元,如果 80000000 美元,否则为零 潜艇 r0,r1,#0 ;仅在 $80000000 时溢出 movvc r0,#0 ;管他呢 ;如果目标的价值是 $7FFFFFFF,如果 $80000000,否则为零 添加 r0,r1,r1,asr #31 ;仅在 $80000000 时溢出 movvc r0,#0 ;如果事先知道进位设置 添加 r0,r1,r1 ;仅在 $80000000 时溢出(值为 1) movvc r0,#0 ;如果已知寄存器 r2 保存 #1 添加 r0,r1,r1,asr #31 ;如果 $80000000,MSB 和进位设置 sbc r0,r2,r0,lsr #31

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    相关资源
    最近更新 更多