如何使用 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 个字。)
我正在学习 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 个字。)