这些汇编代码行的目的是什么?

时间:2017-05-10 18:05:17

标签: c gcc assembly compiler-construction x86

_main:
; create stack frame
pushl   %ebp
movl    %esp, %ebp
; save one local variable
subl    $8, %esp
; zero four rightmost bits of esp
andl    $-16, %esp
; set eax to (0 + 15 + 15) / 2^4 * 2^4 = 16
movl    $0, %eax
addl    $15, %eax
addl    $15, %eax
shrl    $4, %eax
sall    $4, %eax
; set local variable to eax (16)
movl    %eax, -4(%ebp)
movl    -4(%ebp), %eax
; call allocation and main
call    __alloca
call    ___main
; set eax to zero (return value)
movl    $0, %eax
; fold stack frame and return to caller
leave
ret

我使用int main(){return 0;}(在Windows上)编译了一个gcc -S return_zero.c C代码,这就是我得到的内容(我删除了汇编程序指令并添加了解释注释,就像我理解的那样。纠正我,如果我'我错了,拜托。)

我不明白三件事:

  • 为什么编译器将esp对齐到16?
  • 为什么eax设置为16,为什么它以这么复杂的方式完成,为什么局部变量也设置为16?
  • 什么是__alloca和___ main?

我对互联网上的#1和#3都有一些不清楚的解释,所以我想如果有人能够更深入地回答而且#2我没有找到任何解释,所以如果有人能解释它会很棒。

如果需要任何进一步的信息,我会发布评论。

谢谢!

1 个答案:

答案 0 :(得分:1)

Intel Core i5 使用64位架构 解决问题1和部分2,来自 an Overview of x64 Calling Conventions

  

对齐
  大多数结构与其自然对齐对齐。首要的   异常是堆栈指针和malloc或alloca内存,其中   对齐到16个字节以帮助提高性能。对齐上面   16个字节必须手动完成,但由于16个字节是常见的   XMM操作的对齐大小,这适用于大多数代码。对于   有关结构布局和对齐的更多信息,请参阅类型和   存储。有关堆栈布局的信息,请参阅堆栈使用。

关于你问题的一部分: ...为什么以这么复杂的方式完成。只是猜测,但从引用来看,复杂性可能部分是为了适应可移植性。

借用 this post ,(也有标记compiler-constructionassembly& $variable[propertyObject][property] )是一个非常好的逐行解释您尝试解释的一些相同代码。摘录:

  

在步骤1中,我们将指针保存到堆栈上的旧堆栈帧   打电话,pushl%ebp。由于main是第一个被调用的函数,我有   不知道%ebp的先前值是什么。

     

第2步,我们正在进入一个新的堆栈框架,因为我们正在进入   新功能(主要)。因此,我们必须设置一个新的堆栈框架基础   指针。我们使用esp中的值作为堆栈的开头   帧。

     

步骤3.在堆栈上分配8个字节的空间。正如我们提到的   上面,堆栈向低地址增长,因此减去8,   将堆栈顶部移动8个字节   ......

关于致电__alloca& __main

  

...
  步骤12和13设置c库。