2012-03-19 87 views
2

我有一個簡單的代碼:爲什麼「push ebp」會改變ebp的值?

void func() 
{ 
    func2(); 
} 

我省略FUNC2的執行情況和主要因爲它們是不相關的。然後我用WinDBG的追查組件,下面是彙編代碼的輸出執行「FUNC2()」時:在執行

eax=cccccccc ebx=7ffd6000 ecx=00000000 edx=00000001 esi=01faf760 edi=0012ff68 
eip=004113f0 esp=0012fe98 ebp=0012ff68 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func: 
004113f0 55    push ebp 
0:000> t 
eax=cccccccc ebx=7ffd6000 ecx=00000000 edx=00000001 esi=01faf760 edi=0012fe94 
eip=0041140e esp=0012fdc8 ebp=0012fe94 iopl=0   nv up ei pl nz na pe nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000206 
SimpleStack!func+0x1e: 
0041140e e83dfcffff  call SimpleStack!ILT+75(_func2) (00411050) 

我們可以看到,「推EBP」之前,尤指= 0012fe98,和EBP = 0012ff68,但執行「push ebp」後,esp = 0012fdc8,ebp = 0012fe94 ?,所以我有兩個問題: 1.推測推送代碼應該隻影響esp,爲什麼ebp也會改變? 2.推測ebp將推動4個字節堆棧,所以esp的值應該減少4,但我們在這裏看到esp的值減少了208個字節?爲什麼?

+4

它沒有。 「push ebp」的確如它在錫上所說的那樣。請注意,eip增加1E,如果只執行了推動,它會增加1倍。顯然,不止推動已經執行。 – harold 2012-03-19 11:14:27

+1

這裏還有其他事情正在發生。 EIP的差異(0041140e - 004113f0)= 1E字節。太大而不能成爲單一指令。你有多個線程在運行嗎? – adelphus 2012-03-19 11:14:32

+3

@adelphus:你是對的。只需在'004113f0..0041140e'之間進行反彙編即可找到一個序列(在此使用Intel語法):'PUSH EBP; MOV EBP,ESP; PUSH ; ...; SUB ESP,...';這是由編譯器生成的函數入口代碼(稱爲_function prologue_),它使代碼實現了通常的C調用約定/ ABI。在函數結束/返回時,您會找到相應的塊「ADD ESP,...; POP ...;離開; RET'解開了這一切。 – 2012-03-19 12:03:31

回答

1

按照Steve Johnson的指示,我沒有選擇「Source Mode」來跟蹤程序集,事實上在push ebp之後,出現了很多(真的很多!)彙編代碼,它們在選擇「Source Mode」時隱藏了。所以,這種情況下是解決了,但我發現其他問題,首先請參閱我的更完整的代碼:

void func(); 

int main(int argc, char* argv[]) 
{ 
    func(); 
    return 0; 
} 
void func2(); 

void func() 
{ 
    func2(); 
} 

在FUNC,我聲明任何局部變量,下面是當我執行FUNC()在主WinDbg的輸出:

004113c3 50    push eax 
0:000> 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113c4 esp=0012fe98 ebp=0012ff68 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!main+0x24: 
004113c4 e8e0fdffff  call SimpleStack!ILT+420(_func) (004111a9) 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004111a9 esp=0012fe94 ebp=0012ff68 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!ILT+420(_func): 
004111a9 e942020000  jmp  SimpleStack!func (004113f0) 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113f0 esp=0012fe94 ebp=0012ff68 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func: 
004113f0 55    push ebp 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113f1 esp=0012fe90 ebp=0012ff68 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func+0x1: 
004113f1 8bec   mov  ebp,esp 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113f3 esp=0012fe90 ebp=0012fe90 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func+0x3: 
004113f3 81ecc0000000 sub  esp,0C0h 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113f9 esp=0012fdd0 ebp=0012fe90 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func+0x9: 
004113f9 53    push ebx 
0:000> t 
eax=0000000a ebx=7ffda000 ecx=00000000 edx=00000001 esi=01f1f760 edi=0012ff68 
eip=004113fa esp=0012fdcc ebp=0012fe90 iopl=0   nv up ei pl nz na po nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000202 
SimpleStack!func+0xa: 
004113fa 56    push esi 

事實上,我們看到,推EBP後,它是MOV EBP,ESP,這實際上改變EBP,但有一個代碼 「子ESP,0C0H」 下面的 「MOV EBP,ESP」,我知道「 sub esp,num「是爲堆棧幀上的局部變量分配內存空間,但我沒有在func中聲明局部變量,所以我有這樣的問題: 」sub esp,0C0h「是做什麼的回覆? 盯着功能prolog,uf輸出是:

0:000> uf func 
SimpleStack!func [d:\code\simplestack\func.c @ 4]: 
    4 004113f0 55    push ebp 
    4 004113f1 8bec   mov  ebp,esp 
    4 004113f3 81ecc0000000 sub  esp,0C0h 
    4 004113f9 53    push ebx 
    4 004113fa 56    push esi 
    4 004113fb 57    push edi 
    4 004113fc 8dbd40ffffff lea  edi,[ebp-0C0h] 
    4 00411402 b930000000  mov  ecx,30h 
    4 00411407 b8cccccccc  mov  eax,0CCCCCCCCh 
    4 0041140c f3ab   rep stos dword ptr es:[edi] 
    5 0041140e e83dfcffff  call SimpleStack!ILT+75(_func2) (00411050) 
    6 00411413 5f    pop  edi 
    6 00411414 5e    pop  esi 
    6 00411415 5b    pop  ebx 
    6 00411416 81c4c0000000 add  esp,0C0h 
    6 0041141c 3bec   cmp  ebp,esp 
    6 0041141e e818fdffff  call SimpleStack!ILT+310(__RTC_CheckEsp) (0041113b) 
    6 00411423 8be5   mov  esp,ebp 
    6 00411425 5d    pop  ebp 
    6 00411426 c3 
+0

請發佈完整的反彙編功能。使用uf命令來反彙編整個功能。 – 2012-03-20 13:44:42

+0

「uf func」的輸出已發佈,其中包含代碼讀數「sub esp,0c0h」 – wangshuaijie 2012-03-22 01:38:50

+0

您所看到的是編譯器在堆棧中提供了一些空間,以安全檢測堆棧未對齊錯誤和緩衝區溢出。如果你在發佈模式下編譯你的代碼,這一切都將消失。 – 2012-03-22 11:24:15

3

如果您想查看每條單獨的指令在做什麼,則需要禁用源代碼級調試。打開調試菜單並取消選中「源模式」。當你進入源代碼模式時,映射到當前源代碼行的所有指令都會在調試器中斷之前執行。

+0

好點,我會嘗試,也許它是windbg優化的代碼序列,有些東西被隱藏從平淡的視野。 – wangshuaijie 2012-03-20 02:25:04