2015-12-11 42 views
0
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个字节。在汇编中存储eax中的值

1)然后mov eax, [a]将它存储在eax寄存器中。但不是AX只有2个字节的寄存器。它如何存储一个4字节的值?

2)fmt: db "a=%d, eax=%d",10,0我知道fmt是一个位置名称,db声明了一个字节,但接下来的代码是做什么的?

+0

E代表扩展。 EAX存储32位。 – Dzenly

+0

关于#2,我建议您查看有关printf函数如何与格式字符串一起工作的信息。 –

回答

1

术语:从内存中读取(add eax, [a])是一个“负载”。写入内存是一个“商店”(mov [a], eax)。

A dd指令并不“存储”在这个意义上,但。当程序启动时,数据已经存在。使用“puts”或“places”这样的词来避免使用“store”,这在本文中具有技术含义。


  1. eax是4B。 axeax的低2字节,就像alax的低字节。请参阅维基上的链接。我认为维基百科的x86文章有一个显示寄存器子集名称的寄存器图。 (rdi/edi/di/dilrdi/dil仅在64位模式),EFLAGS等提供)

  2. "string", 10, 0是具有换行和终止零字节的字符串。


push ebp     ; calling convention 
    mov ebp, esp 

制作堆栈帧是不是 “调用约定” 的一部分。 gcc现在默认为,因为现代的调试信息格式允许堆栈回溯调试和异常处理,即使没有它。制作堆栈框架是ABI的一个可选部分,但不完全是你称之为“调用约定”的一部分。该术语的含义仅限于函数找到它们的参数,以及它们如何返回它们,除非我错了。

+0

是必要的',10,0'部分,还是只是为了让printf输出看起来不错? – Everythingsucks

+0

@Everythingsucks:如果你想要一个换行符,10是必要的。在Hello World程序中省略'\ n'并亲自查看。当然,'0'是绝对必要的。 C字符串的结尾仅由零字节标记;没有长度存储在其他地方printf知道字符串结束的地方。 –

相关问题