【发布时间】:2022-01-20 17:46:42
【问题描述】:
我目前正在学习 x86 汇编。但是,在将堆栈用于函数调用时,我仍然不清楚。我知道调用指令将涉及将返回地址压入堆栈,然后将程序计数器加载到要调用的函数的地址。 ret 指令会将这个地址加载回程序计数器。
我的困惑是,在过程/函数中调用 ret 指令是否重要?它会始终找到存储在堆栈中的正确返回地址,还是堆栈指针当前必须指向存储返回地址的位置?如果是这样,我们就不能只用 push 和 pop 代替 call 和 ret 吗?
例如,下面的代码可能是第一个进入函数的代码,如果我们将不同的寄存器压入堆栈,必须在寄存器以相反的顺序弹出后才调用ret指令,以便在弹出%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
【问题讨论】:
-
tl;dr 答案摘要:否。
ret=pop eip所以它关心esp指向什么。如果使用得当,它是高级功能的构建块,但它不是魔法。参见说明参考手册:felixcloutier.com/x86/RET.html -
如果这是 AT&T 语法,那么涉及堆栈指针的两个移动都是错误的!如果这是 Intel 语法,请去掉 % 字符。
标签: assembly x86 stack-memory stack-frame stack-pointer