减法在汇编中产生负数 - 十六进制值是多少?

问题描述 投票:0回答:1

我对汇编很陌生,所以我不知道这是否是一个愚蠢的问题,但我有一个问题,要求我阅读以下汇编行并说出之后存储在

%rdi
中的值(
%rdi
中存储的值当前为
0x100
):

subq 0x228, %rdi

我的解决方案是

0xFFFFFFFFFFFFFF80

我首先通过从

-128
减去
0x228
得到
0x100
十六进制,然后取 2 的补码得到
1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000
,我将其转换为十六进制。


我的第一个问题是这是否是正确的大小值:指令末尾有“q”,意思是四字,所以答案应该是 8 个字节,对吗?

我的第二个问题是,这是否是汇编处理负结果的方式:它是否存储该值的 2 的补码形式?

我主要对自己的答案没有信心,因为在其他每一个问题中,我的答案都在 1 到 3 个十六进制数字之间,所以这个似乎不合适。

assembly hex x86-64 att twos-complement
1个回答
0
投票

如果您不确定,请使用调试器自行尝试,甚至可以使用 C 语言使用

uint64_t val = 0x100;
val -= 0x228;
并将结果打印为十六进制。这只是一个二进制减法:位的无符号和 2 的补码解释将给出相同的结果位模式。这就是 2 的补码的要点,它不需要单独的有符号和无符号加法指令。

所以不,该指令不会否定结果(这就是取 2 的补码所做的事情)或类似的事情。 在内部,它“通常”会像进位为 1 的 adc $~0x228, %rdi 一样处理减法,并根据进位的倒数设置 CF。 (与 ARM 不同,在 x86 中,减法后的进位标志是借位标志,而不是反转的。)

~
按位 NOT,因此添加
0xfffffffffffffdd7
加上额外的
1
,通过进位完成,因此它仍然是单个 ALU操作。

我首先得到了
-128

十六进制


正确。

但是看起来您将

-0x128

重新解释为

十进制
-128 (
-0x80
) 并找到了它的位模式。
换成 64 位,

0 - 0x128

(1<<64) - 0x128
相同。 这就是我通常使用计算器程序所做的事情。
结果的高位(前导 

0xFF...

字节)是正确的,但低 2 个字节是错误的。 结果是一个很小的负数,因此符号扩展为64位,设置了很多高位。 这很正常。

如果您的作业需要位模式,则约定的编写方式是使用二进制或无符号十六进制。  

0x100 - 0x228

=

-0x128
的数学值当然是
-296
,您也可以通过将输入转换为十进制并执行
256 - 552 = -296 = -0x128
来获得它。 所以这是用 RDI 表达结果的同样有效的方式。
但请注意,使用除 10 以外的基数并带减号表示负数的情况并不常见,特别是在计算中,十六进制、八进制和二进制通常仅用于位模式/十六进制转储,而不用于由某些位表示的数学值。  从数学上讲,

-0x128

没有任何问题,但只有当你知道它的含义时它才有用,而这个作业可能希望你证明这一点。 :P

    

© www.soinside.com 2019 - 2024. All rights reserved.