Linux后端程序员必备技能之函数栈(2)
完成函数内的运算后,最后将运算结果放入寄存器EAX中,然后调用指令leave和ret。这里面需要说明的是leave指令,该指令相当于下面两条汇编指令。可以对比一下函数入口的汇编指令,其实两者是对称的。leave指令将本帧的栈基址赋值给栈指针(图6中步骤2),然后将其中的内容弹出到RBP中(图6中步骤3)。其实就是RBP指向上一个帧(调用者)的栈帧,也即是一个复原的过程。
图6 函数返回示意图 这样,函数返回后寄存器RBP和RSP从被调用者的栈帧切换到了调用者的栈帧。 通过GDB分析函数调用栈 上面是通过反汇编的方式分析函数的调用栈和栈帧情况。我们还可以通过gdb动态的分析函数栈和栈帧的使用情况。我们依然通过main函数调用func_1函数为例来分析。我们这里在函数func_1的入口处设置一个单点,然后运行程序,程序停止在断点处。如图7是我们逐步执行是函数栈的变化过程,具体细节我们这里就不再赘述,大家可以实际操作一下。 图7 函数栈变化过程 本文的目的是让大家对函数调用栈有个整体的了解,这样对以后程序的疑难杂症就有更多的解决思路。因为在实际生产环境中与栈相关的问题也是比较多的,比如局部变量太多导致的栈溢出,或者踩内存问题引起的栈破坏等等。因此,了解了函数栈的原理,在遇到所谓的莫名其妙问题的时候就会有新的思路。往往很多问题不是问题本身莫名其妙,而是我们的知识储备不够,自己感觉莫名其妙而已。 【编辑推荐】
点赞 0 (编辑:ASP站长网) |