原文:http://blog.csdn.net/yeruby/article/details/39780943程序員
esp是棧指針,是cpu機制決定的,push、pop指令會自動調整esp的值;ruby
ebp只是存取某時刻的esp,這個時刻就是進入一個函數內後,cpu會將esp的值賦給ebp,此時就能夠經過ebp對棧進行操做,好比獲取函數參數,局部變量等,實際上使用esp也能夠;函數
既然使用esp也能夠,那麼爲何要設定ebp呢?spa
答案是爲了方便程序員。.net
由於esp在函數運行時會不斷的變化,因此保存一個一進入某個函數的esp到ebp中 會方便程序員訪問參數和局部變量,並且還方便調試器分析函數調用過程當中的堆棧狀況。前面說了,這個ebp不是必需要有的,你非要使用esp來訪問函數參數 和局部變量也是可行的,只不過這樣會麻煩一些。指針
經過一段程序理解esp和ebp:調試
main() {blog
//執行test前內存
print(int p1,int p2);get
//執行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;