返回地址(保存在堆栈上的EIP
寄存器在返回时使用的那个)是call
之后的下一条指令的地址,还是{{1}的指令地址}}?
编辑:
call
调用p call x
q mov y
x()
或p
时,堆栈上是否有返回地址?
答案 0 :(得分:1)
在调用之后 - 这将是子例程终止时执行的下一条指令。
答案 1 :(得分:1)
处理器将EIP寄存器的值(包含CALL指令后面的指令的偏移量)压入堆栈(稍后用作返回指令指针)。
正如@Jester发布的那样,RTFM。
答案 2 :(得分:0)
call
指令推送返回地址 - 按照您编号"编号"的方式在将执行转移到被调用函数之前,您的行是q
- 在堆栈上。
ret
指令将其弹出 - 您可以说它pop EIP
但这也意味着...... 之前的 ret
,[ ESP ] == EIP
。由于ret
对堆栈没有任何其他作用,但调整了堆栈指针(即ESP
- > ESP + 4
),在您返回时,您应该仍然拥有EIP == [ ESP - 4 ]
。< / p>
你可以这么做:
call func
mov EAX, [ ESP - 4 ]
并且很可能获得该MOV
指令的第一个字节的代码位置。
为什么只有非常可能?答案是,堆栈的未分配部分内的堆栈内容不能得到保证;有异步事件(UN * X信号和其他操作系统中的类似机制)可能会在ret
完成堆栈指针调整/ EIP
更改之间但在该指令实际执行之前中断执行。如果发生这种情况,信号帧可能会覆盖堆栈的未分配部分,从而破坏存储在那里的返回地址。
如果您想要可靠地检索当前的EIP
,请执行与PC相关的呼叫,即“跳过call
指令&#34;”。然后关闭堆栈上的值。即像:
call +5 ;; the size of a call is 5 bytes, so ... "skip yourself"
pop EAX ;; EAX now contains the "return address" - its own EIP
另见先前在SO上解答的Reading Program Counter directly。