负整数的默认存储格式
Default storage format for negative integers
二进制值是否默认以 2 的补码形式存储?
我试验了代码 mov al, -1
并看到 EAX = 000000FF
这是默认的还是我们可以指定使用补码或其他格式
x86 硬件使用 2 的补码有符号整数,例如对于 movsx
符号扩展、imul
/idiv
签名 multiply/divide 和 add
等的 FLAGS 设置(特别是 OF)等说明,包括 sub
/cmp
和 jle
等分支条件。并且没有一个人的补码数学指令(除了 not
,一个人的补码否定,与 neg
二人的补码否定,也就是二进制 0 - x
。)
另请参阅 Understanding Carry vs. Overflow conditions/flags,它准确描述了 2 的补码溢出 (OF) 与进位输出 (CF) 如何进行加法运算。
汇编程序总是1在将源代码中的负数编码为机器代码时使用 2 的补码。mov
-立即在机器代码只是将位模式复制到寄存器中;在 CPU 看到它之前,所有“解释”都已经完成。 (mov reg, sign_extended_narrow_immediate
的唯一情况是 x86-64 mov r/m64, imm32
仅在 64 位模式下。)另请注意,mov al, -1
不会影响 EAX 的高位。如果您看到 0x000000FF
,那是因为 EAX 的高位字节恰好已经为零。
脚注 1:您当然可以编写一个非常奇怪的 x86 汇编程序并执行其他操作。不过,不太可能有人会想要使用它,因为这意味着 add eax, -2
不会将 EAX 的值减少 2。现有 主流汇编器使用相同的数字格式为硬件,硬件为 2 的补码,不可切换。
old_timer 指出一些汇编器(例如用于简单微控制器的简单汇编器)甚至可能根本不支持负常量的语法,在这种情况下,您总是必须手动将常量编码为十六进制或其他任何形式. 0xFF
或 $FF
之类的东西或任何语法。
如果您想使用 1 的补码位模式,请将它们手动编码为十六进制。例如mov al, 0FDh
(~2
) 而不是 mov al, 0FEh
或 -2
.
当然,您必须使用多条指令来实现 1 的补码数学运算。 add
做二进制加法,和2的补码有符号加法是一样的操作,但是不是和1的补码一样的操作。 (这是计算机使用 2 的补码的一个主要原因:+/- 与无符号运算相同,乘法的低半部分也是如此。)
请注意,x86 机器代码具有某些形式的指令,例如 add r/m32, sign_extended_imm8
,在解码时涉及 2 的补码扩展。即高 24 位是第 7 位的副本,复制立即数的最高位以填充寄存器。许多 1 的补码值与此兼容,例如add eax, 0FFFFFFFDh
可以编码为 imm8,汇编程序会为您完成。
二进制值是否默认以 2 的补码形式存储?
我试验了代码 mov al, -1
并看到 EAX = 000000FF
这是默认的还是我们可以指定使用补码或其他格式
x86 硬件使用 2 的补码有符号整数,例如对于 movsx
符号扩展、imul
/idiv
签名 multiply/divide 和 add
等的 FLAGS 设置(特别是 OF)等说明,包括 sub
/cmp
和 jle
等分支条件。并且没有一个人的补码数学指令(除了 not
,一个人的补码否定,与 neg
二人的补码否定,也就是二进制 0 - x
。)
另请参阅 Understanding Carry vs. Overflow conditions/flags,它准确描述了 2 的补码溢出 (OF) 与进位输出 (CF) 如何进行加法运算。
汇编程序总是1在将源代码中的负数编码为机器代码时使用 2 的补码。mov
-立即在机器代码只是将位模式复制到寄存器中;在 CPU 看到它之前,所有“解释”都已经完成。 (mov reg, sign_extended_narrow_immediate
的唯一情况是 x86-64 mov r/m64, imm32
仅在 64 位模式下。)另请注意,mov al, -1
不会影响 EAX 的高位。如果您看到 0x000000FF
,那是因为 EAX 的高位字节恰好已经为零。
脚注 1:您当然可以编写一个非常奇怪的 x86 汇编程序并执行其他操作。不过,不太可能有人会想要使用它,因为这意味着 add eax, -2
不会将 EAX 的值减少 2。现有 主流汇编器使用相同的数字格式为硬件,硬件为 2 的补码,不可切换。
old_timer 指出一些汇编器(例如用于简单微控制器的简单汇编器)甚至可能根本不支持负常量的语法,在这种情况下,您总是必须手动将常量编码为十六进制或其他任何形式. 0xFF
或 $FF
之类的东西或任何语法。
如果您想使用 1 的补码位模式,请将它们手动编码为十六进制。例如mov al, 0FDh
(~2
) 而不是 mov al, 0FEh
或 -2
.
当然,您必须使用多条指令来实现 1 的补码数学运算。 add
做二进制加法,和2的补码有符号加法是一样的操作,但是不是和1的补码一样的操作。 (这是计算机使用 2 的补码的一个主要原因:+/- 与无符号运算相同,乘法的低半部分也是如此。)
请注意,x86 机器代码具有某些形式的指令,例如 add r/m32, sign_extended_imm8
,在解码时涉及 2 的补码扩展。即高 24 位是第 7 位的副本,复制立即数的最高位以填充寄存器。许多 1 的补码值与此兼容,例如add eax, 0FFFFFFFDh
可以编码为 imm8,汇编程序会为您完成。