我目前正在学习 x86 汇编。然而,当使用堆栈进行函数调用时,我仍然不清楚一些事情。据我所知,调用指令将涉及将返回地址压入堆栈,然后将要调用的函数的地址加载到程序计数器。 ret 指令会将这个地址加载回程序计数器。
我的困惑是,在过程/函数中调用 ret 指令是否重要?它总是能找到存储在堆栈上的正确返回地址,还是堆栈指针当前必须指向存储返回地址的位置?如果是这样的话,我们不能只使用push和pop而不是call和ret吗?
例如,下面的代码可能是进入函数的第一个代码,如果我们将不同的寄存器压入堆栈,则必须仅在以相反顺序弹出寄存器之后调用 ret 指令,以便在 pop %ebp 指令之后,堆栈指针将指向堆栈上返回地址所在的正确位置,或者无论在哪里调用它仍然会找到它?提前致谢
push %ebp
mov %ebp, %esp
//push other registers
...
//pop other registers
mov %esp, %ebp
(could ret instruction go here for example and still pop the correct return address?)
pop %ebp
ret
您必须将堆栈和非易失性寄存器保持原样。调用函数不知道您可能对它们做了什么,否则调用函数将简单地继续执行其下一条指令ret
. Only ret
当你清理完之后。
ret
将始终在堆栈顶部查找其返回地址,并且将pop
它进入EIP
。如果ret
是一个“远”返回,那么它也会pop
将代码段放入CS
注册(这也将被推动call
对于“远”呼叫)。因为这些是首先推动的事情call
,它们一定是最后弹出的东西ret
。否则你最终会ret
正在某个未定义的地方。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)