如何解决如何使用 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
在已经加载到 AX 之后,甚至 shl eax,16
/ sar eax,16
。但是,当寄存器中还没有窄值时,MOVSX 是最有效的。
或者使用 AX 中的 16 位加法结果,cwde
只是一种更有效的编写 movsx eax,ax
的方式。
(有趣的事实:CWDE 是可追溯到 8086 的指令的 32 位版本。在 386 之前,您只能使用 AL 或 AX 中的数字有效地进行符号扩展,而不能从任何地方到任何寄存器。)
为了避免在加法中出现有符号溢出的可能性,您可能需要在加法之前movsx
两个输入。例如这使得有可能获得 0x7fff + 0x7fff = 0x0000fffe,65534。
不是 0xffffffffe,也就是 -2,如果在两个正数的 16 位相加溢出产生负结果后进行符号扩展,就会得到它。
(两个 n 位数字的和或差最多需要 n+1 位来精确表示,因此加宽根本不会导致溢出。要溢出 32 位和,您必须添加大约 2^ 16 个字。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。