assembly 如何在ARM中获取寄存器值的二进制补码?

4nkexdtk  于 2022-11-24  发布在  其他
关注(0)|答案(4)|浏览(142)

假设我在寄存器v1中有一个32位有符号整数,我想把这个值的二进制补码存储到另一个寄存器v2中,在普通数学中,这意味着我需要翻转所有32位,然后加1。
我该如何翻转这些位?

46qrfjad

46qrfjad1#

试试这个,(MVN move with not):

MVN v2, v1

这就像你要求的那样“翻转位”。然后你只要做+1:

ADD v2, v1, #1

或者,您可以仅使用NEG v2,v1指令(RSB v2,v1,#0的简写)在单个指令中执行等效操作。

fwzugrvs

fwzugrvs2#

求2的补码的反数(求反)as a compiler can show you的有效方法是用“反减”从零开始减。这也是你在“普通数学”-x = 0-x中要做的

rsbs  r1, r0, #0         @ r1 = 0 - r0

negs  r1, r0             @ same instruction, an alias for RSBS from zero

在Thumb模式下,你通常会希望使用rsbs而不是rsb,因为它比不设置标志的版本更紧凑。只有来自立即数#0rsbs有16位编码,其他立即数需要Thumb 2 32位编码。neg/negs是来自零的rsb的同义词。
要手动进行2的补码恒等式,步骤如下:

mvnMove Not)翻转位(1的补码取反),然后add递增。

mvn  r1, r0             @ r1 = ~r0
add  r1, r1, #1         @ ++r1

但实际上,你永远不会这样做,当一个指令可以做的时候,用两个指令。有时有用的是从这个或另一个值的算术右移中得到0-1,并使用eorsub来执行x ^ (-1) + (-1)或带零的无操作。这给你一个绝对值或有条件地对另一个数求反。使用2的补码恒等式。
但在ARM上,这比预测效率低:如果结果是正的,你可以只执行rsbs和 predicate mov,或者更好的tst和 predicate rsbs到绝对值,没有额外的寄存器。这比bithack的方式要短。在其他ISA上,你可能仍然会求反和条件移动,或者如果指令数相等,使用bithack。

@@ absolute value of r0
    tst   r0, r0
    it    lt                    @ free in ARM mode, separate 16-bit insn in Thumb
    neglt r0, r0
dohp0rv5

dohp0rv53#

或者比MVN慢一点:
MOV v0,-1
MUL v2,v1,v0

eivnm1vs

eivnm1vs4#

似乎没有专门的命令来反转ARM中的寄存器。但下面有一个简单快速的替代命令(使用gdb/qemu检查):
rsb接收,接收,-1
这将执行以下操作:
输出= -1 -输入
这是得到逻辑NOT的正确过程。

相关问题