在汇编

时间:2015-12-11 06:26:22

标签: assembly

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声明了一个字节,但其余的代码是做什么的?

1 个答案:

答案 0 :(得分:1)

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

dd指令在这个意义上并没有“存储”。程序启动时,数据已存在。使用像“puts”或“places”这样的词来避免使用“store”,这在这种情况下具有技术含义。

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

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

  3.    push ebp                  ; calling convention
       mov ebp, esp
    

    制作堆栈帧不是“调用约定”的一部分。 gcc现在默认为-fomit-frame-pointer,因为现代调试信息格式允许堆栈回溯以进行调试和异常处理,即使没有它也是如此。制作堆栈帧是ABI的可选部分,但并不严格地称为“调用约定”的一部分。该术语的含义仅限于函数找到它们的args,以及它们如何返回它们,除非我弄错了。