该函数内存关系如下。
Screen Shot 2017-06-10 at 4.37.33 PM.png
大致步骤如下
1.先从右到左将b,a的值压栈,将main函数的esp栈顶确定。
2.再执行foo函数之前,先把foo函数执行完后的下一步指令,80483e9(就是函数中return 0)压栈。
3.修改程序计数器eip,然后跳转到foo函数。让ebp栈底寄存器现在指向foo函数,再将main函数栈底的值ebp(main)压栈。此刻,foo函数栈上第一个内存空间保存的是main函数的栈底值。
4.将d,c的值压栈,然后确定foo函数esp栈顶。
5.再执行bar函数之前,先把bar函数执行完后的下一步指令,80483c2(foo的返回指令,返回到main函数)压栈。
6.修改程序计数器eip,然后跳转到bar函数。
7.当bar函数返回了e值之后,会修改程序计数器eip,然后执行80483c2,返回到main函数。然后继续修改程序计数器eip,执行80483e9(return 0)。ebp和esp的值也相应变化。
《C程序设计》一书中对于函数之间调用提出两个注意点:
- 函数运行期间调用另外一个函数,在运行被调用函数之前,系统需要先完成3件事情:
1.将所有的实参、返回地址等信息传递给被调用函数保存
2.为被调用函数局部变量在栈上分配内存
3.将控制转移到被调用函数入口
- 被调用函数返回调用函数之前,系统也需要相应的完成3件事情:
1.在栈中保存被调用函数的计算结果(返回值)
2.释放在栈中为被调用函数分配的数据区
3.依照被调用函数保存的返回地址将控制转移到调用函数
网友评论