我正在攻读Uni的计算机体系结构和汇编编程课程。前段时间我们学会了如何在ASM中编写函数并从C调用它们。有一件事我不明白 - 在每个ASM函数的开头,讲师总是做两个指令;
pushl %ebp
movl %esp, %ebp
我不明白为什么他这样做,以及它在调用时对函数有什么影响。在我的Intel Mac上,在为IA32编写程序集时,无论是否包含这些指令或只是跳过它,似乎没有任何区别。
有人可以告诉我在调用这些指令时实际发生了什么,以及为什么总是在ASM函数的开头调用它们?最好是在GNU ASM中,虽然Intel ASM也没问题。
答案 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上非常流行,但是......
您可以查看enter
和leave
做什么。