Linux
分类: 网络与安全
2014-05-21 18:14:01
{
int a, b;
a = m;
b = n;
}
int main(void)
{
...
func(m, n);
L: 下一条语句
...
}
在main调用func函数前,栈的情况,也就是说main的栈帧:
从低地址esp到高地址ebp的区域,就是当前main函数的栈帧。当main中调用func时,写成汇编大致是:
push m
push n; 两个参数压入栈
call func; 调用func,将返回地址填入栈,并跳转到func
push ebp; 新函数要有自己栈帧,必须保存main栈帧底部;栈顶不用保存,因为main栈帧顶部是func栈帧底部(两栈相邻)
mov ebp, esp; 上一栈帧的顶部,就是这个栈帧的底部
目前的栈的使用情况如下:
新栈帧开始:
sub esp, 8; // int a, b 声明了两个int,所以esp减小8个字节来为a,b分配空间
mov dword ptr [esp+4], [ebp+12]; // a=m
mov dword ptr [esp], [ebp+8]; // b=n
ret 8; 返回,8是参数占用字节数,当返回后,esp-8,释放参数m,n的空间
由此可见,通过ebp,能够很容易定位到上面的参数。当从func函数返回时,首先esp移动到栈帧底部(即释放局部变量),
然后把上一个函数的栈帧底部指针弹出到ebp,再弹出返回地址到cs:ip上,esp继续移动划过参数。这样,ebp,esp就回到了调用函数前的状态,即现在恢复了原来的
main的栈帧。