1. 程式人生 > >彙編指令ebp與esp的關係與作用

彙編指令ebp與esp的關係與作用

彙編指令ebp與esp的關係與作用
可以看到,初始情況下,ebp此時值為0012FEDC,也就是棧幀的地址,而棧頂地址esp值為0012FDFC。可以看到兩個值有一定的關係。而 幀指標 的地址較高。

     然後我們讓它執行前兩句,push ebp,mov ebp,esp

彙編指令ebp與esp的關係與作用

可以看到前兩句已經執行了,那麼ebp跟esp的值也發生了變化。esp=0012FDF8,ebp=0012FDF8。為神馬?一句句解讀,push ebp,向棧裡面壓入了一個東西,那麼棧頂此時應該發生變化了,也就是地址-4位元組。為什嗎是減法呢?因為是向低地址增長的,這點一定得注意。所以此時esp變化成了0012FDFC-4=OO12FDF8.至於ebp也等於0012FDF8就不解釋了

彙編指令ebp與esp的關係與作用

此時呢,觀察現在的值。棧頂esp=0012FDF4,而ebp=0012FDF8;沒啥好說的,此時的棧頂已經又跑上去了,說明又有元素壓棧了。那麼執 行這句mov esp,ebp之後,不用說,esp跟ebp都會變成0012FDF8.我們重點看下一幅,執行完pop,讓ebp出棧,後會發生神馬。

彙編指令ebp與esp的關係與作用

此時ebp已經出棧了,來看看那他們的值,esp=0012FDFC,ebp=0012FEDC.首先,ebp出棧了,這個時候棧空了,所以棧頂會變成初始時的值001212FDFC。相當於上圖中的esp=0012FDF8+4=0012FDFC.注意出棧,則棧頂+4,然後呢。ebp為啥變成了0012FEDC初始的值?ebp不是一直儲存著esp的初始地址麼?       所以重點就在pop這個語句了。pop ebp究竟表達神馬意思?ebp的值起初存在了棧中,出棧以後,它的值就恢復了原樣。所一句灰常重要啊彙編指令ebp與esp的關係與作用

。pop的意思也許就是把彈出的值賦給我們的變數,pop  ebp,也就是把存在棧中的值彈出來賦給ebp。

所以我們在囉唆幾句:

1、兩句的mov ebp,esp實際上是把ebp進棧後的棧頂地址給了ebp。

2、在ebp沒有出棧錢,它會一直儲存ebp進棧以後的棧頂值,也就是1的值。

3、在ebp出棧前,需要把esp恢復到只有ebp在棧中時的值。

4、出棧後,esp自然恢復到ebp進棧以前的初始值,而pop ebp則恢復了ebp的初始值。

5、pop的語義很重要,pop  ebp的意思是把當前棧頂的元素出棧,送入ebp中,而不是讓ebp出棧,這點必須明確!彙編指令ebp與esp的關係與作用

       說完這個以後,我也有了疑問,因為從上面的解釋來看,似乎棧裡面的東西沒有清空?就直接把esp恢復到了ebp的值,這是為神馬呢?發現這就是所謂的棧平 衡問題,先不糾結了,只要有前兩句push ebp, mov ebp,esp跟最後兩句mov esp,ebp,pop  ebp就夠了,這樣肯定不會有問題。

      搞點學習筆記,比較下cmp跟test的指令,這兩個都是比較檢測指令。

     cmp  eax,xxxx,意思是讓兩者相減,但是並不儲存運算的結果,只用來影響相應的標誌位,從而判斷是否執行跳轉,比如說一下的例子是很常見的:

   cmp eax,1

   JE xxxx

      JE的跳轉條件是:ZF=0,也就是當兩者相等的時候,執行跳轉。那麼這個命令組合起來就是表示:如果eax=1,執行跳轉

   順便 再說下JNE,JNE的意思是jump if not eaqual,也就是跟JE的判斷條件相反

       然後說下TEST吧,test eax,xxx:意思是讓eax跟xxx執行與運算,同樣也是不儲存運算結果,而影響相應的標誌位,TEST呢經常用來幹下面這件事情.

    test eax,eax

    JZ    xxxx

    意思很明顯,就是檢測EAX的值是不是0,所以這個語句就是檢測判斷語句。JZ嘛就是jump if zero。組合起來也就是表示如果eax為0,執行跳轉到xxxx。

      覺得還是CALL指令最難理解,它先把IP壓棧,然後跳到子程式裡面去執行東西,最後IP出棧,指令返回到先前執行的地方。繼續OD吧。

 __________________________________________________________________________________________________________

       經過了激勵的思想鬥爭,我終於想清楚了這個過程。現在可以毫無壓力的,淡定的說,ebp儲存的是棧幀起始的其實地址,也就是一個函式屬於自己的記憶體那一塊 的最高地址,而esp就儲存了當前的這一塊地址中已經使用的最低地址,說起來可能有些拗口。但是這對於深刻理解這個過程是至關重要的。

       有一句話讓我想明白了這個道理,ebp總是跟舊的棧幀的頂部相鄰。這樣我們就可以理解為什麼,呼叫一個函式的時候需要push ebp,那就儲存舊的棧幀,同時也給出了我們得到舊的ebp的方法,一旦當前的棧幀使用完畢以後,這個最後彈出來的ebp就指明瞭我們怎麼樣回到舊的函式 的棧幀,或者知道那個呼叫我們的上一層函式的棧幀。mov ebp,esp這句話很有迷惑性。其實很好理解,這個告訴了我們新的棧幀是怎麼建立的,其實就是直接的拿當前函式(ebp已經入棧後)的棧頂當做新的棧幀 頭部,因為此時已經有esp=ebp了,而舊的ebp被我們儲存在了棧裡面。

      關於這個佈局,CSAPP說的很清楚,深刻的理解了以上兩句的作用,很多事情都能順理成章的想通了。

       其實說白了,ebp只有一個作用,就是用來暫時儲存當前函式棧的起始地址,因為舊的棧幀跟新的棧幀是相鄰的,ebp相當於起一個咋暗示的temp的作用。

轉自:http://hi.baidu.com/anheizzq/item/1c0899622926c81e7ddecca3