ASM函数调用返回地址
返回地址( EIP
寄存器返回时保存在堆栈中的那个地址)是在call
后的下一条指令的地址,还是它是call
的指令地址?
编辑:
p call x
q mov y
调用x()
p
或q
时,返回地址是堆栈中的吗?
在调用之后 - 这将是子例程终止时执行的下一条指令。
处理器将EIP寄存器的值(包含CALL指令之后指令的偏移量)压入堆栈(稍后用作返回指令指针)。
正如@Jester发布的,RTFM。
该call
指令将返回地址-在路上你“编号为”你行那将会q
-在堆栈上执行转移到被调用函数之前。
ret
指令将其弹出 - 你可以说它pop EIP
。
但是这也意味着...在ret
之前, [ ESP ] == EIP
。 由于ret
对堆栈没有其他任何东西,但是调整堆栈指针(即ESP
- > ESP + 4
),到您返回时,您仍然应该拥有EIP == [ ESP - 4 ]
。
你可以这样做:
call func
mov EAX, [ ESP - 4 ]
并且很可能获得该MOV
指令的第一个字节的代码位置。
为什么只有很可能? 答案是堆栈未分配部分内的堆栈内容不能保证; 有异步事件(UN * X信号和其他操作系统中的类似机制)可能会在执行堆栈指针调整/ EIP
更改之后但在该指令实际执行前的ret
之间中断执行。 如果发生这种情况,信号帧可能会覆盖未分配的堆栈部分,从而破坏存储在那里的返回地址。
如果您想要可靠地检索当前的EIP
,请执行只是“跳过call
指令”的PC相关呼叫。 然后弹出堆栈上的值。 即喜欢:
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上回答的,直接阅读程序计数器。
链接地址: http://www.djcxy.com/p/80365.html