为什么在每个ASM函数的开头都有pushl%ebp和movl%esp,%ebp?

时间:2014-04-03 17:10:35

标签: c function assembly instructions

我正在攻读Uni的计算机体系结构和汇编编程课程。前段时间我们学会了如何在ASM中编写函数并从C调用它们。有一件事我不明白 - 在每个ASM函数的开头,讲师总是做两个指令;

pushl   %ebp
movl    %esp, %ebp

我不明白为什么他这样做,以及它在调用时对函数有什么影响。在我的Intel Mac上,在为IA32编写程序集时,无论是否包含这些指令或只是跳过它,似乎没有任何区别。

有人可以告诉我在调用这些指令时实际发生了什么,以及为什么总是在ASM函数的开头调用它们?最好是在GNU ASM中,虽然Intel ASM也没问题。

3 个答案:

答案 0 :(得分:5)

这是正确堆栈展开所必需的约定的一部分。 %ebp基指针指向调用者的堆栈帧。调用约定是通过将​​其推入堆栈来保存调用者的基指针。请参阅Agner Fog全面的呼叫约定文档中的第9章异常处理和堆栈展开

http://www.agner.org/optimize/calling_conventions.pdf

如果您想使用调试器(例如gdb)调试程序,并希望它向您显示backtrace,那么您需要遵循该调用约定。

http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_42.html

  

回溯是对程序如何到达的总结。对于许多帧,它显示每帧一行,从当前正在执行的帧(帧0)开始,然后是其调用者(帧1),并在堆栈上。

答案 1 :(得分:2)

根据编译器的不同,帧指针是可选的(您可以省略使用Microsoft编译器的帧指针)。在这种情况下,局部变量和参数作为ESP的偏移而不是EBP被访问​​,并且EBP被释放以用作通用寄存器(尽管使用EBP作为地址的一部分默认使用s而不是ds段寄存器)。

答案 2 :(得分:1)

原因很简单:

上述函数prolog保存前一帧指针,并为新帧设置一个新指针。无框架代码在16bit / 32bit x86上非常流行,但是......

您可以查看enterleave做什么。