力求内容精简,以图会意
如下为代码:
#include <iostream>
using namespace std;
int fun(int a,int b)
{
int sum = a + b;
return sum;
}
int main()
{
int a = 2, b = 3;
fun(a,b);
return 0;
}
以下为汇编代码(main函数):
0x401356 push %ebp //保存上一过程帧指针
0x401357 mov %esp,%ebp //初始化当前帧指针,为上一过程栈顶指针
0x401359 and $0xfffffff0,%esp //保证栈顶指针为16倍数
0x40135c sub $0x20,%esp //申请0x20字节大小的栈
0x40135f call 0x41c2e0 <__main> //跳转到main函数
0x401364 movl $0x2,0x1c(%esp) //初始化变量a,b。局部变量,如图
0x40136c movl $0x3,0x18(%esp)
0x401374 mov 0x18(%esp),%eax //复制a,b放栈
0x401378 mov %eax,0x4(%esp)
0x40137c mov 0x1c(%esp),%eax
0x401380 mov %eax,(%esp)
0x401383 call 0x401340 <fun(int, int)>
0x401388 mov $0x0,%eax
0x40138d leave
0x40138e ret
内存分布:
在调用一个函数时,首先要保存当前帧栈的帧指针,每个函数在栈空间中都由自己的一段内存,用来放局部变量,以及一些其他信息(如地址返回值)。这个内存的头尾地址即由CPU寄存器ebp和esp保存。
每个局部变量都映射在栈内存中。每个过程内存都这样分布。 而进程的整个栈空间作为一个段,位置大小信息由操作系统保存在对应的数据结构中。另外,过程的栈空间大小是在编译时确定的,每个过程都有自己的符号表,遍历符号表来确定所需的栈空间。