標籤:一個棧 函數返回 技術分享 androi csdn 理解 過程 point 重點
cp: http://blog.csdn.net/hutao1101175783/article/details/40128587
(1)ESP:棧指標寄存器(extended stack pointer),其記憶體放著一個指標,該指標永遠指向系統棧最上面一個棧幀的棧頂。
(2)EBP:基址指標寄存器(extended base pointer),其記憶體放著一個指標,該指標永遠指向系統棧最上面一個棧幀的底部。
【本次重點內容:瞭解幾個常見的寄存器名字,記住eax一般用來儲存函數的傳回值,記住esp是棧頂指標寄存器,ebp是棧底指標寄存器。】
ESP 中的指標將一直指向這個新位置, 所以 ESP 中的地址資料是動態.
-----
cp : http://blog.csdn.net/yeruby/article/details/39780943
esp是棧指標,是cpu機制決定的,push、pop指令會自動調整esp的值;
ebp只是存取某時刻的esp,這個時刻就是進入一個函數內後,cpu會將esp的值賦給ebp,此時就可以通過ebp對棧進行操作,比如擷取函數參數,局部變數等,實際上使用esp也可以;
既然使用esp也可以,那麼為什麼要設定ebp呢?
答案是為了方便程式員。
因為esp在函數運行時會不斷的變化,所以儲存一個一進入某個函數的esp到ebp中會方便程式員訪問參數和局部變數,而且還方便調試器分析函數調用過程中的堆棧情況。前面說了,這個ebp不是必須要有的,你非要使用esp來訪問函數參數和局部變數也是可行的,只不過這樣會麻煩一些。
通過一段程式理解esp和ebp:
main() {
//執行test前
print(int p1,int p2);
//執行test後
}
分析下上面程式的調用原理,假設執行print前esp=Q:
push p2; //函數參數p2入棧,esp=Q-4H
push p1; //函數參數p1入棧,esp=Q-8H
call print; //函數返回地址入棧,esp=Q-0CH
//現在進入print內,做些準備工作:
push ebp; //保護先前ebp指標,ebp入棧,esp=Q-10H
mov esp,ebp; //設定ebp等於當前的esp
// 此時,ebp+0CH=Q-4H,即p2的位置
// 同樣,ebp+08H=Q-8H,即p1的位置
// 下面是print內的一些操作:
sub esp,20H; //設定長度為10H大小的局部變數空間,esp=Q-20H
// ... ...
// 一系列操作
// ... ...
add esp,20H; //釋放局部變數空間,esp=Q-10H
pop ebp; //出棧,恢複原先的ebp的值,esp=Q-0CH
ret 8; //ret返回,彈出先前入棧的返回地址,esp=Q-08H,後面加運算元8H為平衡堆棧
// 之後,彈出函數參數,esp=Q,恢複執行print函數前的堆棧;
圖示,注意棧在記憶體中的生長方向是逆向:
執行push p2;前,esp=Q;
執行push p2;過程中,esp-=4H,p2入棧;
執行push p2;後,esp=Q-4H;
[Android Pro] ESP和EBP 棧頂指標和棧底指標