2010-09-03 113 views
37

我在程序集中使用了堆棧,但我沒有關於推ebp和pop ebp的想法。有關在程序集中推ebp和pop ebp指令的說明

.intel_syntax noprefix 

.include "console.i" 

.text 

askl: .asciz "Enter length: " 
askb: .asciz "Enter breadth: " 
ans: .asciz "Perimeter = " 

_entry: 

    push ebp  # establishing stack-frame 
    mov ebp, esp 
    sub esp, 12 

    Prompt askl 
    GetInt [ebp-4]  # length 
    Prompt askb 
    GetInt [ebp-8]  # breadth 

    mov eax, [ebp-4] # eax = l 
    add eax, [ebp-8] # eax = l + b 
    add eax, eax # eax = 2 * (l + b) 
    mov [ebp-12], eax 

    Prompt ans 
    PutInt [ebp-12] 
    PutEoL 

    mov esp, ebp 
    pop ebp  # unwinding stack-frame 
    ret 

.global _entry 

.end 
+1

爲什麼你發佈整個代碼時,只有6條線懷疑? – Searock 2010-09-04 04:56:40

+8

給予更多的上下文總是最好的。這就是說,真正的問題是非常模糊的,並會使用更多的解釋。 – 2010-09-06 13:39:11

回答

58

我不知道這是否是您的疑問,但也許你想知道這一點:

push ebp 
mov ebp, esp 
sub esp, 12 

第2行所知道的序言裝配功能。它存儲以前的基址指針(ebp),並將基指針設置爲棧頂。這意味着所有的堆棧內容都保存在堆棧中,所以函數可以在堆棧中彈出/彈出。

sub esp,12行爲功能中的本地變量節省空間。

在你到底有:

mov esp, ebp 
pop ebp 
ret 

這是序言做反,所以之前的環境可以恢復。

這是你的疑問嗎? :)

+5

另請注意,您有一條叫做'leave'的指令,這正是'pop esp,ebp'和'pop ebp'所做的。 – jyz 2013-05-13 11:53:37

37

ebp被稱爲基指針或幀指針。在進入你的功能時,你按下它(保存調用函數的值)。然後,您將esp(堆棧指針)複製到ebp,以便ebp現在指向您的函數的堆棧幀。在函數結束時,您將彈出ebp,以便恢復調用函數的值。

爲了澄清究竟是怎麼回事,push指令將來自指定寄存器(在這種情況下爲ebp)的值放入堆棧,並將堆棧指針遞減適當的數量。 pop操作是相反的 - 它會增加堆棧指針並從堆棧中獲取一個值並將其放入指定的寄存器中。