函数调用后堆栈的内容
Contents of stack after function call
我正在阅读一本书,其中解释了调用函数时 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 [=26=]x2
0x08048476 : push [=26=]x1
0x08048478 : call 0x804843b
0x0804847d : add [=26=]x10,%esp
function() 的第一条和最后几条指令是:
0x0804843b : push %ebp
0x0804843c : mov %esp,%ebp
0x0804843e : sub [=27=]x38,%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
后面应该是 return 位置 0x0804847d
和函数参数 0x00000001
和 0x00000002
。但是我不知道什么是 0xffffcd68
。这是ebp
的地址吗?
是函数开头ebp
的值
这是 push %ebp
和 x86 堆栈完全降序这一事实的结果。
它是调用者帧指针。
请注意,编译器更新他们处理堆栈的方式比书籍作者更新他们的书的方式要频繁得多。
特别是:对齐、帧指针遗漏、RVO、隐式参数等可能会让您失望。
我正在阅读一本书,其中解释了调用函数时 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 [=26=]x2 0x08048476 : push [=26=]x1 0x08048478 : call 0x804843b 0x0804847d : add [=26=]x10,%esp
function() 的第一条和最后几条指令是:
0x0804843b : push %ebp 0x0804843c : mov %esp,%ebp 0x0804843e : sub [=27=]x38,%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
后面应该是 return 位置 0x0804847d
和函数参数 0x00000001
和 0x00000002
。但是我不知道什么是 0xffffcd68
。这是ebp
的地址吗?
是函数开头ebp
的值
这是 push %ebp
和 x86 堆栈完全降序这一事实的结果。
它是调用者帧指针。
请注意,编译器更新他们处理堆栈的方式比书籍作者更新他们的书的方式要频繁得多。
特别是:对齐、帧指针遗漏、RVO、隐式参数等可能会让您失望。