觀察棧幀和EBP ESP暫存器

2021-06-16 11:41:56 字數 4050 閱讀 6979

本文將用windbg觀察棧幀以及ebp、esp暫存器的變化過程。 

首先我們先寫一段簡單的**進行實驗。 

int main() 

int a(int a) 

禁用visualstudio的自動優化,然後編譯成release版本,然後用windbg開啟可執行檔案。 

觀察main函式的反彙編**。 

0:000> uf main 

teststack!main [c:\users\xiaohaitao\documents\visual studio 2008\projects\teststack\teststack\test.cpp @ 7]: 

7 01391000 55 push ebp 

7 01391001 8bec mov ebp,esp 

7 01391003 83ec08 sub esp,8 

8 01391006 c745fc07000000 mov dword ptr [ebp-4],7 

9 0139100d 6a07 push 7 

9 0139100f e81c000000 call teststack!a (01391030) 

9 01391014 83c404 add esp,4 

9 01391017 8945f8 mov dword ptr [ebp-8],eax 

10 0139101a 8b45f8 mov eax,dword ptr [ebp-8] 

11 0139101d 8be5 mov esp,ebp 

11 0139101f 5d pop ebp 

11 01391020 c3 ret 

在main開始處設定斷點,然後執行到斷點處。 

0:000> bp main 

0:000> g 

breakpoint 0 hit 

eax=003c19f8 ebx=00000000 ecx=6f7bb6f0 edx=00000000 esi=00000001 edi=01393374 

eip=01391000 esp=002afaf0 ebp=002afb30 iopl=0 nv up ei pl zr na pe nc 

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 

teststack!main: 

01391000 55 push ebp 

觀察此時的棧幀 

0:000> kb 

childebp retaddr args to child 

002afaec 013911ae 00000001 003c2c70 003c19f8 teststack!main [c:\users\xiaohaitao\documents\visual studio 2008\projects\teststack\teststack\test.cpp @ 7] 

002afb30 77571194 7ffd6000 002afb7c 7797b495 teststack!__tmaincrtstartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582] 

002afb3c 7797b495 7ffd6000 77e5d1ed 00000000 kernel32!basethreadinitthunk+0xe 

002afb7c 7797b468 013912f6 7ffd6000 00000000 ntdll!__rtluserthreadstart+0x70 

002afb94 00000000 013912f6 7ffd6000 00000000 ntdll!_rtluserthreadstart+0x1b 

此時的棧幀基址為:002afaec 

觀察此處的內容: 

0:000> dd 002afaec l4 

002afaec 00000001 013911ae 00000001 003c2c70 

我們知道,每乙個棧幀基址的內容應該是上一層函式的棧幀基址,也就是位址002afaec處的內容應該是002afb30才對,而現在這個值為00000001,第二個值013911ae為函式返回值,第三值00000001為傳遞給該函式的第乙個引數。和kb列印的結果對比,函式返回值和引數是沒有錯的。但是第乙個值00000001是什麼呢? 

觀察ebp,esp暫存器。 

0:000> r ebp, esp 

ebp=002afb30 esp=002afaf0 

我們發現ebp的值是上乙個棧幀的基址,而不是本棧幀的位址。而esp的值002afaf0,比當前棧幀基址002afaec要高4個位元組。我們知道esp是始終指向棧頂的,而棧空間是由高位址向低位址分配,當前棧幀基址002afaec比棧頂002afaf0還低4個位元組,說明當前棧幀基址指向未使用的棧空間,是乙個隨機值。 

然後執行main函式的開始前兩句彙編。 

0:000> u main 

teststack!main [c:\users\xiaohaitao\documents\visual studio 2008\projects\teststack\teststack\test.cpp @ 7]: 

01391000 55 push ebp 

01391001 8bec mov ebp,esp 

01391003 83ec08 sub esp,8 

01391006 c745fc07000000 mov dword ptr [ebp-4],7 

0139100d 6a07 push 7 

0139100f e81c000000 call teststack!a (01391030) 

01391014 83c404 add esp,4 

01391017 8945f8 mov dword ptr [ebp-8],eax 

0:000> bp 01391003 //在01391003 83ec08 sub esp,8 處設定斷點 

0:000> g //繼續執行 

breakpoint 1 hit 

eax=003c19f8 ebx=00000000 ecx=6f7bb6f0 edx=00000000 esi=00000001 edi=01393374 

eip=01391003 esp=002afaec ebp=002afaec iopl=0 nv up ei pl zr na pe nc 

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 

teststack!main+0x3: 

01391003 83ec08 sub esp,8 

此時再觀察esp, ebp暫存器 

0:000> r esp, ebp 

esp=002afaec ebp=002afaec 

0:000> dd 002afaec l4 

002afaec 002afb30 013911ae 00000001 003c2c70 

此時ebp=002afaec的內容已經由00000001變成了002afb30, 由前面的棧回溯可以看出002afb30正是上一級函式的棧幀位址,說明執行完基址入棧以後,main函式的棧幀基址的內容和ebp的內容都已經被正確設定。 

總結: 

esp是棧指標暫存器,總是指向棧頂。 

ebp是棧幀基址暫存器,不是棧基址暫存器,指向棧幀的基址。 

在乙個函式的最開始處,以下兩條指令未執行時: 

00a01000 55              push    ebp 

00a01001 8bec            mov     ebp,esp 

ebp指向的上乙個棧幀的基址。 

esp指向棧頂,比該函式的棧基址高4個位元組。 

列印該函式棧基址的內容,由於上乙個棧幀的基址還未入棧,所以此時棧幀基址指向的為隨即內容。 

最近,看一下ebp的概念: 

(1)esp:棧指標暫存器(extended stack pointer),其內存放著乙個指標,該指標永遠指向系統棧最上面乙個棧幀的棧頂。 

(2)ebp:基址指標暫存器(extended base pointer),其內存放著乙個指標,該指標永遠指向系統棧最上面乙個棧幀的底部

暫存器和棧的關係

前言 暫存器作用 可以儲存位址或整數資料 程式計數器 用來記錄某些重要的程式狀態 條件碼暫存器 其他用來儲存臨時資料,過程引數和區域性變數,以及函式的返回值 在這裡需要說明一下,這是x86 64 處理單元的一組16個儲存64位值的通用目的暫存器 8086時代,是 ax到 bp ia32架構 擴充套件...

CS 暫存器 和 IP 暫存器

下面將要介紹的是一組非常非常重要的暫存器,即 cs ip cs ip 兩個暫存器指示了 cpu 當前將要讀取的指令的位址,其中cs 為 段暫存器,而ip 為指令指標暫存器。什麼叫做指示了 cpu 當前將要讀取的指令呢?在 8086 cpu 中,為什麼 cpu 會自動的執行指令呢?這些指令肯定是存放在...

除錯暫存器和測試暫存器

1 除錯暫存器 80386為除錯提供了硬體支撐。在80386晶元內有8個32位的除錯暫存器dr0 dr7,如圖2.6所示。這些暫存器可以使系統程式設計人員定義4個斷點,用它們可以規定指令執行和資料讀寫的任何組合。dr0 dr3是線性斷點位址暫存器,其中儲存著4個斷點位址。dr5 dr6是兩個備用的除...