call
之後的下一條指令的地址,還是call
的指令地址,返回地址(保存在堆棧中的EIP
寄存器返回時使用的地址)?ASM函數調用返回地址
編輯:
p call x
q mov y
呼喚x()
p
或q
當堆棧上的返回地址?
call
之後的下一條指令的地址,還是call
的指令地址,返回地址(保存在堆棧中的EIP
寄存器返回時使用的地址)?ASM函數調用返回地址
編輯:
p call x
q mov y
呼喚x()
p
或q
當堆棧上的返回地址?
在調用之後 - 這將是子例程終止時執行的下一條指令。
處理器將EIP寄存器(包含CALL指令之後的指令的偏移量)的值壓入堆棧(稍後用作返回指令指針)。
由於@Jester發佈,RTFM。
考慮到我什至不知道那裏是一本「手冊」(假設我找到了)閱讀它會有點困難.... – user997112
理查德可能脾氣暴躁,但這些概念上的字面意義實在是太多了。一個更詳細的方式來重述他的snark評論是「如果你寫低層次細節很重要的軟件,暫停在那裏,併成爲你的CPU的指令集參考最好的朋友」。注意這種行爲是由CPU架構決定的,而不是編譯器! –
這個隨機谷歌的第3頁是有用的http://mai.kvk.uni-obuda.hu/documents/tantargy/8086-instruction-set-overview.pdf。請注意PUSH,POP,CALL,RET和IRET –
call
指令在將執行轉移到被調用函數之前,將返回地址 - 按照您編號爲q
的行編號 - 在堆棧中。
ret
指令將其彈出 - 您可以說它的確如此pop EIP
。
但是這也意味着... 之前ret
,[ ESP ] == EIP
。由於ret
對堆棧沒有做任何其他操作,但是調整堆棧指針(即ESP
- >ESP + 4
),到您返回時,仍然應該有EIP == [ ESP - 4 ]
。
你可以做的,因此:
call func
mov EAX, [ ESP - 4 ]
,並很可能得到的代碼位置爲MOV
指令的第一個字節。
爲什麼只有很可能?答案是堆棧未分配部分內的堆棧內容不能保證;在執行堆棧指針調整/ EIP
更改但在該指令實際執行之前,會出現異步事件(UN * X信號以及其他操作系統中的類似機制),這些事件可能會中斷正在執行的ret
之間的執行。如果發生這種情況,信號幀可能會覆蓋未分配的堆棧部分,從而破壞存儲在那裏的返回地址。
如果您想要可靠地檢索您當前的EIP
,請執行一個PC相對調用,它只是「跳過call
指令」。然後彈出堆棧上的值。即像:
call +5 ;; the size of a call is 5 bytes, so ... "skip yourself"
pop EAX ;; EAX now contains the "return address" - its own EIP
參見Reading Program Counter directly如以前SO回答了。
這是'call'後面的指令,'ret'應該返回。下一次請參閱指令集參考。 – Jester
看到這個堆棧溢出帖子:http://stackoverflow.com/questions/17514774/how-do-called-functions-return-to-their-caller-after-being-called –