函数调用时的堆栈结构分析

void func(int a, int b)
{
	int c;
	c=a+b;
}

int main(void)
{
	func(3,4);
	return 0;
}


编译后的汇编代码如下图所示,当然main函数也是一个调用函数,但是我们不看它,直接看调用func函数的汇编代码。从第11行开始,首先,从最后一个表格看一下压栈前的ebp和esp的值,ebp=0x0012ff80,esp=0x0012ff34(ebp为栈基址指针,esp为栈顶指针,压栈和出栈改变的是esp,压栈方向向下,也即地址减少),然后开始对参数3和4进行压栈,压栈顺序从后往前,接着调用call指令进入函数体(第2行),这里函数的返回地址将自动压栈;接着进入函数后,前两条指令push ebp和mov ebp, esp将改变堆栈结构,为什么要采用这种方式还不太明白,接着开始执行函数中的代码。执行完成后,弹出堆栈中的内存,然后又分别调用mov ebp, esp和push ebp回复最先的堆栈结构,最后执行ret退出函数(最先返回地址自动弹出)。

 

 

 

总结:

       1. 对于X86CPU的堆栈生长方向是地址递减的方向。

       2. 函数调用时参数的压栈顺序是逆序的,最后一个参数先压栈,第一个参数最后压栈。

       3. 进入函数后,会对原有堆栈结构进行重新调整,首先将ebp压栈;然后将ebp指向当前的esp,也就是改变栈底指针,并且还改变了esp栈顶指针的值,就好像从新开辟了新的堆栈结构;接着在新的堆栈上进行函数代码实现;最后恢复原先栈结构。

       4. call指令会自动将返回地址(eip)压栈,ret指令也会自动将返回地址(eip)出栈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值