esp跟ebp跟蹤記錄

發現文字描述還是太沒有快感。上幾幅圖,來說明這個調試過程更
好。此文對於深刻理解ebp,esp是具有長遠意義的

可以看到,初始情況下,ebp此時值爲0012FEDC,也就是棧幀的地址,而
棧頂地址esp值爲0012FDFC。可以看到兩個值有一定的關係。而幀指針的地址
較高。
     然後我們讓它執行前兩句,push ebp,mov ebp,esp

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

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

此時ebp已經出棧了,來看看那他們的值,esp=0012FDFC,ebp=0012FEDC.
首先,ebp出棧了,這個時候棧空了,所以棧頂會變成初始時的值0012FDFC。相
當於上圖中的esp=0012FDF8+4=0012FDFC.注意出棧,則棧頂+4,然後呢。ebp
爲啥變成了0012FEDC初始的值?ebp不是一直保存着esp的初始地址麼?
       所以重點就在pop這個語句了。pop ebp究竟表達神馬意思?ebp的值起
初存在了棧中,出棧以後,它的值就恢復了原樣。所一句灰常重要啊。pop的意
思也許就是把彈出的值賦給我們的變量,pop  ebp,也就是把存在棧中的值彈出
來賦給ebp。
        所以我們在囉唆幾句:
1、兩句的mov ebp,esp實際上是把ebp進棧後的棧頂地址給了ebp。
2、在ebp沒有出棧前,它會一直保存esp進棧以後的棧頂值,也就是1的值。
3、在ebp出棧前,需要把esp恢復到只有ebp在棧中時的值。
4、出棧後,esp自然恢復到ebp進棧以前的初始值,而pop ebp則恢復了ebp
的初始值。
5、pop的語義很重要,pop  ebp的意思是把當前棧頂的元素出棧,送入ebp中,
而不是讓ebp出棧,這點必須明確!
       說完這個以後,我也有了疑問,因爲從上面的解釋來看,似乎棧裏面的
東西沒有清空?就直接把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的
作用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章