2012-03-19 194 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

相关问题