對暫存器ESP和EBP的一些理解
阿新 • • 發佈:2019-02-03
PS:EBP是當前函式的存取指標,即儲存或者讀取數時的指標基地址;ESP就是當前函式的棧頂指標。每一次發生函式的呼叫(主函式呼叫子函式)時,在被呼叫函式初始時,都會把當前函式(主函式)的EBP壓棧,以便從子函式返回到主函式時可以獲取EBP。
下面是按呼叫約定__stdcall 呼叫函式test(int p1,int p2)的彙編程式碼
假設執行函式前堆疊指標ESP為0xAAAAAAA ;EBP為0xAAAAAB0
push p2 ;引數2入棧, ESP -= 4h , ESP =
0xAAAAAAA - 4h = 0xAAAAAA6
push p1 ;引數1入棧, ESP -= 4h , ESP = 0xAAAAAAA - 8h = 0xAAAAAA2
call test ;壓入返回地址 ESP -= 4h, ESP = 0xAAAAAAA-
0Ch = 0xAAAAA9D,注意:這裡是test函式的返回地址,即在程式碼段中的地址(偏移)。
;//進入函式內
{
push ebp ;保護先前EBP指標, EBP入棧(即0xAAAAAB0入棧,注意與返回地址區別), ESP-=4h, ESP = 0xAAAAA99
mov ebp, esp ;設定EBP指標指向棧頂
0xAAAAA99
mov eax, dword ptr [ebp+0ch] ;ebp+0ch為0xAAAAAA6 即引數2的位置
mov ebx, dword ptr [ebp+08h] ;ebp+08h為0xAAAAAA2,即引數1的位置
sub esp, 8 ;區域性變數所佔空間ESP-=8, ESP = 0xAAAAA91
...
add esp, 8 ;釋放區域性變數, ESP+=8, ESP = 0xAAAAA99
pop ebp ;出棧,恢復EBP, ESP+=4, ESP = 0xAAAAA9D,即把棧中地址0xAAAAA99的內容pop到ebp中
ret 8 ;ret返回,彈出返回地址,ESP+=4, ESP=0xAAAAAA2, 後面加運算元8為平衡堆疊,ESP+=8,ESP=0xAAAAAAA,
恢復進入函式前的堆疊.
}
看完彙編後,再看EBP和ESP的定義,哦,豁然開朗,
原來ESP就是一直指向棧頂的指標,而EBP只是存取某時刻的棧頂指標,以方便對棧的操作,如獲取函式引數、區域性變數等。