【问题标题】:Nasm - How does the program keep track of which register has stored negative or positive valuesNasm - 程序如何跟踪哪个寄存器存储了负值或正值
【发布时间】:2025-12-30 05:15:07
【问题描述】:

显然有标志标志。但是当我有一个代码块时:

             ;starts with parry, zero set
mov eax, 100 ; mov does not affect the flags
neg eax      ; sets carry, adjust and sign, unsets zero
mov ebx, 4000000000; mov does not affect the flags
mov ecx, eax ; mov does not affect the flags
mov edx, 50  ; mov does not affect the flags

add ebx, edx ; unsets all set flags, value of ebx is 4000000050

我很难理解程序如何知道add ebx, edx4000000050

请记住,符号标志仍然设置为否定eax

因为汇编没有像 C 这样区分 signedunsignedebx 的类型,所以设置了最高位,存储在 ebx 中的值可能是它的实际值,也可能是它的 2 的补码。我们不知道。

至少这是我的理解。那么程序是如何知道ebx+4000000000 而不是二进制的2 的补码是4000000000 的负值。

【问题讨论】:

    标签: assembly nasm cpu-registers flags twos-complement


    【解决方案1】:

    处理器不知道。程序员有责任跟踪哪些寄存器/内存位置包含有符号数,哪些包含无符号数。

    32 位寄存器可以存储 -2147483648 .. 2147483647 范围内的数字 0 .. 4294967295 范围内的数字。处理器不知道程序员想要这两个范围中的哪一个使用。 2 的补码算法的美妙之处在于处理器无需知道即可执行大多数操作。

    处理器确实需要知道的一些操作是:除法、乘法(其结果是操作数宽度的两倍)以及比较。对于乘法和除法,有符号和无符号有单独的操作码。为了比较,比较操作码是相同的,但是用于检查比较结果的条件分支操作码是不同的,具体取决于程序员是否要将操作数视为有符号或无符号。

    【讨论】:

    • 我应该添加一些带有实际数字的示例,但是我没时间了,所以希望我以后可以回来做,或者其他人可以添加它们。
    • 所以当我比较 ebx 和 ecx 时,ebx 包含 -2147483648 和 ecx 包含 2147483648 比较的操作码是相同的。但是之后使用jzjnzjge等时,它们的操作码会有所不同吗?那是组装自己解决的问题吗?因为我从不使用取决于寄存器内容值是正数还是负数的特殊指令。很抱歉,我无法理解。
    • @MenNotAtWork:注意ja(上面无符号)和jg`(有符号更大)是不同的指令,具有不同的助记符和不同的操作码。 (全部在felixcloutier.com/x86/jcc 中列出)。另请参阅teaching.idallen.com/dat2343/10f/notes/040_overflow.txt,了解如何通过相同的 ALU 操作设置不同的标志(进位与溢出和符号)。
    • 不,汇编器无法解决它,因为它不知道。此外,这不是操作数是 positive 还是 negative 的问题。您需要记住的是操作数是 signed 还是 unsigned。你可以使用jge(例如)作为有符号的操作数,jae 用于无符号的操作数。 jejne 当然是一样的。