x86汇编寄存器:有符号或无符号?

8
我知道这是一个非常简单的问题,但我找不到答案。 x86汇编中的寄存器(eax、ebx、edx等)是有符号还是无符号的?如果它们默认为有符号,那么如果我们将变量声明为unsigned int,计算机如何知道如何将寄存器视为无符号的呢?谢谢!

3
寄存器只是保存固定位数的比特。使用的指令将决定如何处理这些比特。内存也是如此。 - Jeff
2
有些指令,如加或减,对于有符号或无符号的值是相同的。借位/进位标志设置时假定数字为无符号,而溢出标志则假定数字为带符号的。其他指令,如乘法或除法,具有带符号和无符号版本。大多数设置标志的指令将把符号标志(SF)设置为结果的最高位,如果假定该数字为有符号,则为符号标志。 - rcgldr
7
类型是高级语言提供的一种幻觉。 - harold
2个回答

11

CPU并不知道,也不在意。相反,在特定操作中设置了Flags寄存器中的位,程序如何处理这些标志取决于源代码所告诉它的内容。

例如,

mov eax, 0FFFFFFFFh
test eax, eax
js isNegative

对比。

mov eax, 0FFFFFFFFh
test eax, eax
jb isNegative

第一个跳到'IsNegative',因为test在这里设置了符号标志。第二个没有,因为test将进位标志复位为0,而jb仅在它为1时跳转。


2
请注意,对于无符号比较,x < 0始终为false,因此在实际编程中,您实际上不会编写test same,same / jb。该条件已知对于每个可能的EAX值(包括零)都是false(不采取)。也许更好的例子是cmp eax,10用于有符号与无符号eax <10。(然后,您需要使用jl而不是js来进行有符号条件。) - Peter Cordes

1

x86中的32位寄存器默认为无符号。例如,从32位操作数移动到64位寄存器时,在长模式下始终进行零扩展。但每个指令根据其目的对寄存器都有自己的解释,例如“add”指令可以使用带符号或无符号的寄存器。有关详细信息,请参阅英特尔文档。


5
说得有些别扭了。在 mov eax, ecx 中,两个操作数都是32位的。写入32位寄存器总是会隐式地将其零扩展到完整的64位寄存器,但是唯一显式执行32位到64位移动的方法是使用 movsxd rax, ecx(进行符号扩展)。mov rax, ecx 无法汇编(操作数大小不匹配)。没有带有32位源的 movzx 形式,因为你不需要它(只需使用 mov)。因此,实际上不可能* 明确地 * 零扩展64位。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接