如何使用 DWORD PTR(汇编语言)打印负整数

how to print negative integer using SWORD PTR(assembly lang)

我正在学习 x86 汇编语言,不知道如何使用 Irvine32 库打印负整数。

INCLUDE Irvine32.inc

.data

arry    SWORD   10, -20, 30

.code
main PROC
    mov     eax,    0
    mov     esi,    OFFSET arry
    mov     ax,     SWORD PTR [esi]
    add     esi,    TYPE arry
    add     ax,     SWORD PTR [esi]
    call    WriteInt
    exit
    ;call   DumpRegs
    

main ENDP
end main

我期望的结果是-10,但控制台打印了+65526。我不知道 WriteInt 函数是如何工作的,但它似乎将 ax 中的值识别为无符号值。

如果我这样修改我的代码,WriteInt 函数就会给我正确的结果。(-10)

...
    mov     eax,    10
    sub     eax,    20
    call    WriteInt
...

我想从内存中读取数据并加减整数。如果我想打印为有符号整数,我该怎么做?

movsx eax, SWORD PTR [esi] 将其符号扩展为 WriteInt 的双字寄存器。

WriteInt 总是查看整个 32 位,而你给它的 32 位数字(位模式 0x0000fff6),解释为 32 位 2 的补码,代表一个正数。

如果有一个 WriteShort 函数,您可以调用它,它会查看第 15 位而不是第 31 位来确定数字是否为负数,但是当我们可以符号扩展时就不需要了直到一个完整的寄存器。


请注意您在加载 AX 之前使用的 mov eax,0:您通过这样做明确地进行了零扩展,这是一种模仿 movzx eax, word ptr [esi] 的低效方式。 (如果你不这样做,EAX 的高 16 位将保存调用 main 的代码中的任何垃圾。)

还有其他方法可以进行 2 的补码符号扩展,即将数字的符号位复制到完整寄存器的高位。例如,当寄存器中还没有窄值时,cwde after already loading into AX, or even shl eax, 16 / sar eax, 16. But MOVSX 是最有效的。

或者用 AX 中的 16 位加法结果,cwde 只是一种更有效的写法 movsx eax, ax.

(有趣的事实:CWDE 是可追溯到 8086 的指令的 32 位版本。在 386 之前,您只能使用 AL 或 AX 中的数字有效地进行符号扩展,而不能从任何地方到任何寄存器。 )


为了避免在加法中出现符号溢出的可能性,您可能希望在加法之前movsx两个输入。例如这使得获得 0x7fff + 0x7fff = 0x0000fffe, 65534 成为可能。
不是 0xfffffffe,又名 -2,如果在两个正数的 16 位加法溢出产生负结果后进行符号扩展,就会得到它。

(两个 n 位数字的和或差最多需要 n+1 位才能准确表示,因此加宽根本不可能溢出。要溢出 32 位和,您必须添加大约2^16 个字。)