这篇是 C 函数调用原理的最终篇,如果错过前面的铺垫知识可以翻看前面两篇文章。
C 函数的返回过程是 C 函数调用过程的逆过程,所以理解了 C 函数调用过程后返回过程就比较容易理解。
步骤 1 和步骤 2 的 leave 指令做了两个任务:重置 esp 并将它指向到当前栈帧开始的地方,另一个是恢复在 ebp 中保存的值。这两个操作在逻辑上是独立的,因此,在图中将它们分开来说。
在 leave 运行后,恢复了前一个栈帧。add 函数调用唯一留下的东西就是在栈顶部的返回地址。它包含了运行完 add 函数之后在 main 函数中必须运行的指令的地址。
ret 指令用来处理它:它弹出返回地址到 eip 寄存器(32 位的指令寄存器),这个寄存器指向下一个要执行的指令。现在程序将返回到 main 函数,主要部分如下:
main 函数从 add 函数中拷贝返回值到本地变量 answer,然后,运行它自己的结语epilogue,这一点和其它的函数是一样的。最后一步执行的是,返回到 C 运行时库(libc),它将退回到操作系统中。
C 函数调用原理的讲解到此结束,至此,总算踏完了第一步,心里顿时舒畅了许多。。。
在最后说一下写这三篇文章的感受:文章本身并不花什么时间,花时间的是之前的资料收集和整理。要弄懂一个概念也需要查看很多资料,而且为了严谨需要参考很多国外的论坛博客和官方文档,对于我这个英语渣渣看得还是蛮累的(虽然有谷歌翻译减少了工作量,但是翻译准确度还有待提高)。