ASM函数调用返回地址

时间:2014-03-13 02:21:31

标签: assembly x86 x86-64

返回地址(保存在堆栈上的EIP寄存器在返回时使用的那个)是call之后的下一条指令的地址,还是{{1}的指令地址}}?

编辑:

call

调用p call x q mov y x()p时,堆栈上是否有返回地址?

3 个答案:

答案 0 :(得分:1)

在调用之后 - 这将是子例程终止时执行的下一条指令。

答案 1 :(得分:1)

处理器将EIP寄存器的值(包含CALL指令后面的指令的偏移量)压入堆栈(稍后用作返回指令指针)。

正如@Jester发布的那样,RTFM。

答案 2 :(得分:0)

call指令推送返回地址 - 按照您编号"编号"的方式在将执行转移到被调用函数之前,您的行是q - 在堆栈上。

ret指令将其弹出 - 您可以说它pop EIP 但这也意味着...... 之前的 ret[ ESP ] == EIP。由于ret对堆栈没有任何其他作用,但调整了堆栈指针(即ESP - &gt; 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