函数调用栈实例分析,有图有真相

函数调用栈是理解函数调用的关键一环,也是理解递归思想的重要基础,本博文综合源码,汇编语言,寄存器,内存进行详细阐述

目录

一 源码

二 汇编语言预计调用栈分析

2.1 编译器进入调试状态,并查看源码和对应的汇编代码

2.2 分析main 函数的函数栈

2.3. add 函数的调用和返回

三 总结


一 源码

int add(int a, int b){
	return a + b;
}

int main()
{
	int a = 0;
	int c = 3;
	int m = add(0, 3);
	return 0;
}

 对上源码在windows vc6.0 下进行编译

二 汇编语言预计调用栈分析

2.1 编译器进入调试状态,并查看源码和对应的汇编代码

2.2 分析main 函数的函数栈

  1. 将调用main()函数的EBP 入栈
  2. mov ebp, esp 将 esp 赋值给ebp, 使得 ebp = esp 都指向 main()的EBP
  3. sub esp, 4ch, 即将esp 往下拉4ch
  4. int a =0, int c= 3, 即push 3, push 0, esp 继续往下移动
  5. 执行 add(0, 3) ,即  ,                                                                                                           
  6. 函数将跳入 00401005, 再跳入 00401020(即 add 函数)
  7. 在跳入00401020 的时候 将 0040107F 赋值给EIP                     

      

2.3. add 函数的调用和返回

add 函数的调用栈变化过程和main() 函数基本相同,这里不再重复。重点分析add()函数的返回

即 mov  esp, ebp

pop ebp 

ret 

这三句

当执行mov esp, ebp 时,将 ebp  的值赋给esp , 而此时EBP 正指向 main()函数的 EBP 

当执行pop ebp 时, 值将ebp 执行的内存的值赋值给 ebp , 此时 ebp 回到 调用 add()之前指向的位置 

执行完ret 后,EIP 重新指向 0040107F, 程序继续往下走

三 总结

通过以上分析,关于函数调用栈,可得出以下重要结论

1. 调用函数之前,首先将 参数入栈

2. 当刚进入被调用的函数,将返回地址入栈(返回地址即是调用函数完成后继续往下走的地址), 将调用函数的EBP 入栈

3. 函数返回时,调用函数的EBP 被回复到调用之前,ESP 也恢复到调用之前,EIP 指向返回地址(即程序继续往下走)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值