extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 5 ; int a=5;
fmt: db "a=%d, eax=%d",10,0 ; The printf format, "\n",'0'
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; calling convention
mov ebp, esp
mov eax, [a] ; put a from store into register
add eax, 2 ; a+2
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
call printf ; Call C function
add esp, 12 ; pop stack 3 push times 4 bytes
mov esp, ebp ; returning convention
pop ebp ; same as "leave" op
mov eax,0 ; normal (no error) return value
ret ; return
我有点困惑。我知道dd
声明了一个4字节的值并在其中存储了5个。
1)然后mov eax, [a]
将其存储在eax寄存器中。但是,AX不仅仅是一个2字节的寄存器。它如何存储4字节值?
2)fmt: db "a=%d, eax=%d",10,0
我知道fmt是一个位置名称,db声明了一个字节,但其余的代码是做什么的?
答案 0 :(得分:1)
术语:从内存中读取(add eax, [a]
)是一种“负载”。写入内存是一个“商店”(mov [a], eax
)。
但dd
指令在这个意义上并没有“存储”。程序启动时,数据已存在。使用像“puts”或“places”这样的词来避免使用“store”,这在这种情况下具有技术含义。
eax
是4B。 ax
是eax
的低2字节,就像al
是ax
的低字节一样。请参阅x86 wiki上的链接。我认为维基百科的x86文章有一个寄存器图,显示了寄存器子集的名称。 (rdi / edi / di / dil
(rdi/dil
仅适用于64位模式),EFLAGS
等。)
"string", 10, 0
是一个带换行符和终止零字节的字符串。
push ebp ; calling convention
mov ebp, esp
制作堆栈帧不是“调用约定”的一部分。 gcc现在默认为-fomit-frame-pointer
,因为现代调试信息格式允许堆栈回溯以进行调试和异常处理,即使没有它也是如此。制作堆栈帧是ABI的可选部分,但并不严格地称为“调用约定”的一部分。该术语的含义仅限于函数找到它们的args,以及它们如何返回它们,除非我弄错了。