我正在阅读Duntemann的书(第3版),刚刚开始学习x86程序集。我使用的是Fedora 23(64位)的变体。以下是代码:
section .data
section .text
global _start
_start:
nop
; Put your experiments between the two nops...
mov eax,0FFFFFFFFh
mov ebx,02Dh
dec ebx
inc eax
; Put your experiments between the two nops...
nop
我的makefile如下:
sandbox: sandbox.o
ld -o sandbox sandbox.o -melf_i386
sandbox.o: sandbox.asm
nasm -f elf -g -F stabs sandbox.asm -l sandbox.lst
所以你可以看到我已经注意组装一个32位可执行文件,而不是64位。但问题是,在dec ebx
指令之前,AF
和SF
标志的设置与本书所声称的相反。在insight
中运行程序向我显示了32位寄存器,这进一步确保可执行文件为32位。以下是gdb
指令前dec ebx
显示的状态。
(gdb) info reg
eax 0xffffffff -1
ecx 0x0 0
edx 0x0 0
ebx 0x2d 45
esp 0xffffce80 0xffffce80
ebp 0x0 0x0
esi 0x0 0
edi 0x0 0
eip 0x804806b 0x804806b <_start+11>
eflags 0x202 [ IF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x0 0
Pg 217中的Duntemann的版本显示AF
和SF
标志已设置。我的代码出了什么问题?
答案 0 :(得分:5)
正如Margaret Bloom评论的那样,mov
指令不设置标志!事实上,它对标志完全没有影响,这使得它在你想要设置寄存器或内存的内容而不破坏标志的当前状态的情况下非常有用。
这在the official Intel IA-32 ISA reference manual中有记载,但如果你像我一样,那你就是懒惰。幸运的是,我们很幸运。有几种人将官方文档的部分内容上传到他们的网站,只需使用Google搜索“x86”加上指令助记符的名称即可轻松找到这些文档。例如,我对“x86 mov”的最高结果是this page。请注意以下部分:
受影响的旗帜
无。
当然,其他说明会说不同的东西。 add
指令实际上设置了所有标志,如您所见[{3}}。
因此,查看您的代码,执行将从设置为无意义的垃圾值的标志开始。从技术上讲,它们将包含它们最后设置的任何值,但是在程序的上下文中这是没有意义的,因为您没有将它们设置为任何东西,因此不能依赖它们被设置为有意义的值!
nop
和mov
指令都不会影响标志的值,因此它们将继续包含垃圾值。
在执行dec
指令之前,标志不会包含有意义的值。然后,根据here,将根据递减操作的结果设置溢出,符号,零,调整和奇偶校验标志。进位标志不受dec
的影响,因此将继续包含垃圾值。
the documentation以与dec
完全相同的方式设置标志,因此溢出,符号,零,调整和奇偶校验标志将发生变化,但进位标志将不会(并将继续)包含垃圾值。)
我没有你所引用的那本书的副本,所以我不知道它实际上是什么意思。如果它只是在代码执行中的那一点显示寄存器/标志状态的转储,那么标志只是垃圾值而不是重要的 - 你应该关注寄存器中的值如何变化为mov
指令的结果。如果它实际上意味着mov
指令设置了标志,那么这本书就有一个错误。 : - )