[英]Assembly x86 - “leave” Instruction
據說“離開”指令類似於:
movl %ebp, %esp
popl %ebp
我理解movl %ebp, %esp
部分,並且它用於釋放存儲的內存(如本問題中所述 )。
但是popl %ebp
代碼的目的是什么?
LEAVE
是ENTER
的對應物。 ENTER
指令通過首先將EBP
推入堆棧然后將ESP
復制到EBP
設置堆棧幀,因此LEAVE
必須執行相反的操作,即將EBP
復制到ESP
,然后從堆棧中恢復舊的EBP
。
如果您想了解有關ENTER
和LEAVE
如何工作的更多信息,請參閱英特爾軟件開發人員手冊第1卷中名為“塊結構語言的程序調用”一節。
enter n,0
完全等同於(應該替換為)
push %ebp
mov %esp, %ebp # ebp = esp, mov ebp,esp in Intel syntax
sub $n, %esp # allocate space on the stack. Omit if n=0
leave
完全等同於
mov %ebp, %esp # esp = ebp, mov esp,ebp in Intel syntax
pop %ebp
enter
非常慢,編譯器不使用它,但leave
很好。 ( http://agner.org/optimize )。 如果編譯器完全使用堆棧框架(至少是gcc),它們會使用leave
。 但是如果esp
已經等於ebp
,那么pop ebp
是最有效的。
popl
指令恢復基指針, movl
指令恢復堆棧指針。 基指針是堆棧的底部,堆棧指針是頂部。 在離開指令之前,堆棧看起來像這樣:
----Bottom of Caller's stack----
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack/Bottom of Callee's stack---- (%ebp)
...
Callee's
Variables
...
---Bottom of Callee's stack---- (%esp)
在移動被調用者堆棧的movl %ebp %esp
,堆棧如下所示:
----Bottom of Caller's stack----
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack/Bottom of Callee's stack---- (%ebp) and (%esp)
在恢復調用者堆棧的popl %ebp
之后,堆棧如下所示:
----Bottom of Caller's stack---- (%ebp)
...
Caller's
Variables
...
Function Parameters
----Top of Caller's Stack---- (%esp)
enter
指令保存調用者堆棧的底部並設置基指針,以便被調用者可以分配他們的堆棧。
另請注意,雖然大多數C編譯器都以這種方式分配堆棧(至少在優化時關閉),如果編寫匯編語言函數,如果需要,可以使用相同的堆棧幀,但是必須一定要pop
你push
它的堆棧,否則當你返回時你會跳轉到一個垃圾地址(這是因為call <somewhere>
意味着push <ret address>
[或push %eip
], jmp <somewhere>
, ret
表示跳轉到堆棧頂部的地址[或pop %eip
]。 %eip
是保存當前指令地址的寄存器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.