我正在读一本书,其中解释了调用函数时ebp
和eip
寄存器如何工作。提供下图:
这里array
是一个局部函数变量。函数参数为 a
和 b
。实际的 C 代码如下所示:
#include <stdio.h>
void function(int a, int b)
{
int array[8];
}
int main()
{
function(1,2);
return 0;
}
我使用 gcc -m32 -g function.c
进行编译,并在 gdb
中运行该程序。命令 disas main
显示(跳过了一些行):
0x08048474 : push $0x2 0x08048476 : push $0x1 0x08048478 : call 0x804843b 0x0804847d : add $0x10,%esp
function() 的前几条指令和最后几条指令是:
0x0804843b : push %ebp 0x0804843c : mov %esp,%ebp 0x0804843e : sub $0x38,%esp 0x08048441 : mov %gs:0x14,%eax 0x08048447 : mov %eax,-0xc(%ebp) 0x0804844a : xor %eax,%eax 0x0804844c : nop ... 0x0804845e : leave 0x0804845f : ret
当我检查ebp
的内容时:
(gdb) x/4xw $ebp 0xffffcd48: 0xffffcd68 0x0804847d 0x00000001 0x00000002
据我了解,在堆栈中,ebp
后面应该跟有返回位置 0x0804847d
以及函数参数 0x00000001
和 0x00000002
。但是我不知道0xffffcd68
是什么。这是ebp
的地址吗?
最佳答案
它是函数开头的ebp
的值。
这是 push %ebp
的结果,而且 x86 堆栈是完全降序的。
它是调用者帧指针。
<小时/>请注意,编译器更新处理堆栈的方式比书籍作者更新书籍的方式要频繁得多。
特别是:对齐、帧指针遗漏、RVO、隐式参数等可能会让您感到困惑。
关于函数调用后栈的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53461045/