我正在读一本书,该书解释了调用函数时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
的地址吗?
答案 0 :(得分:1)
它是函数开头的ebp
的值。
这是push %ebp
的结果,并且x86堆栈是Full Descending。
它是呼叫者框架指针。
请注意,编译器更新其处理堆栈的方式要比书籍作者对其书籍进行更新的频率高。
特别是:对齐,省略帧指针,RVO,隐式参数等可能会使您失望。