Почему «push ebp» меняет значение ebp? - PullRequest
2 голосов
/ 19 марта 2012

У меня есть простой код:

void func()
{
    func2();
}

Я опускаю реализацию func2 и main, поскольку они не имеют значения.Затем я использовал 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)

Мы можем видеть, что перед выполнением «push ebp», esp = 0012fe98, иebp = 0012ff68, но после выполнения «push ebp», esp = 0012fdc8, ebp = 0012fe94 ?, поэтому у меня есть два вопроса: 1. Предположительно, push-код должен влиять только на esp, почему также изменяется ebp?2. Предположительно push ebp будет помещать 4 байта в стек, поэтому значение esp должно уменьшиться на 4, но мы видим здесь, что значение esp уменьшается на 208 байтов?Почему?

Ответы [ 2 ]

3 голосов
/ 19 марта 2012

Если вы хотите увидеть, что делает каждая отдельная инструкция, вам нужно отключить отладку на уровне источника. Откройте меню отладки и снимите флажок «Режим источника». При переходе в исходный режим все инструкции, сопоставленные с текущей строкой исходного кода, выполняются до того, как отладчик прервется.

1 голос
/ 20 марта 2012

По указанию Стива Джонсона, я снимаю флажок с «Source Mode», чтобы отслеживать сборку, действительно после push ebp, следует много (действительно много!) Кода ассемблера, который был ранее скрыт при проверке «Source Mode».Таким образом, этот случай решен, но я нашел другие проблемы, во-первых, пожалуйста, посмотрите мой более полный код:

void func();

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

void func()
{
    func2();
}

В func я не объявляю локальные переменные, следующий вывод windbg при выполнении func () вmain:

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

На самом деле мы видим, что после push ebp именно mov ebp, esp на самом деле изменяет ebp, но после «mov ebp, esp» следует код «sub esp, 0C0h»,Я знаю, что «sub esp, num» предназначен для выделения пространства памяти для локальных переменных в фрейме стека, но я не объявлял локальные переменные в func, поэтому у меня есть следующие вопросы: Что здесь делает «sub esp, 0C0h»?Начиная с пролога функции, вывод 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
...