стек, регистр esp - PullRequest
       1

стек, регистр esp

1 голос
/ 18 октября 2011

Я копирую этот код из книги. В каждом комментарии я ставлю число, а затем задаю вам вопрос (1,2,3,4), относящийся к строкам кода, прокомментированным этим числом. Надеюсь, все в порядке.

1) ESP указывает на эти значения буфера. ПОЧЕМУ мы не видим 0x41 для «А» здесь ????

2) ESP указывает на переменную память, которая должна содержать 31337, что составляет 0x7a69 в шестнадцатеричном формате. ПОЧЕМУ ЭТО НЕ ВМЕСТЕ СОДЕРЖИТ ЭТОТ НОМЕР 0xbffff89c ???

3) Указывает на указатель предыдущего кадра стека, который в этом случае содержит правильный адрес.

4) Обратный адрес. Также правильно.

5) Аргументы. Также исправьте значения.

Так что же происходит в 1) и 2)? Это набивка?

Большое спасибо.

void test_function(int a, int b, int c, int d) {
  int flag;
  char buffer[10];
  flag = 31337;
  buffer[0] = 'A';
}

int main() {
  test_function(1, 2, 3, 4);
}


GDB debug session
Breakpoint 2, test_function (a=1, b=2, c=3, d=4) at stack_example.c:5
5 flag = 31337;
(gdb) i r esp ebp eip
esp 0xbffff7c0 0xbffff7c0
ebp 0xbffff7e8 0xbffff7e8
eip 0x804834a 0x804834a <test_function+6>
(gdb) disass test_function
Dump of assembler code for function test_function:
0x08048344 <test_function+0>: push ebp
0x08048345 <test_function+1>: mov ebp,esp
0x08048347 <test_function+3>: sub esp,0x28
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41
0x08048355 <test_function+17>: leave
0x08048356 <test_function+18>: ret
End of assembler dump.
(gdb) print $ebp-12
$1 = (void *) 0xbffff7dc
(gdb) print $ebp-40
$2 = (void *) 0xbffff7c0
  (gdb) x/16xw $esp  
    0xbffff7c0: 0x00000000 0x08049548 0xbffff7d8 0x08048249  // 1
    0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9  // 1 
    0xbffff7e0: 0xb7fd6ff4                                   // 1
    0xbffff89c                                               // 2
    0xbffff808                                               // 3
    0x0804838b                                               // 4
    0xbffff7f0:                                              // 4
    0x00000001 0x00000002 0x00000003 0x00000004              // 5




reader@hacking:~/booksrc $ gcc -g stack_example.c
reader@hacking:~/booksrc $ gdb -q ./a.out
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) disass main
Dump of assembler code for function main():
0x08048357 <main+0>: push ebp
0x08048358 <main+1>: mov ebp,esp
0x0804835a <main+3>: sub esp,0x18
0x0804835d <main+6>: and esp,0xfffffff0
0x08048360 <main+9>: mov eax,0x0
0x08048365 <main+14>: sub esp,eax
0x08048367 <main+16>: mov DWORD PTR [esp+12],0x4
0x0804836f <main+24>: mov DWORD PTR [esp+8],0x3
0x08048377 <main+32>: mov DWORD PTR [esp+4],0x2
0x0804837f <main+40>: mov DWORD PTR [esp],0x1
0x08048386 <main+47>: call 0x8048344 <test_function>
0x0804838b <main+52>: leave
0x0804838c <main+53>: ret
End of assembler dump
(gdb) disass test_function()
Dump of assembler code for function test_function:
0x08048344 <test_function+0>: push ebp
0x08048345 <test_function+1>: mov ebp,esp
0x08048347 <test_function+3>: sub esp,0x28
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41
0x08048355 <test_function+17>: leave
0x08048356 <test_function+18>: ret
End of assembler dump
(gdb)

1 Ответ

5 голосов
/ 18 октября 2011

'A' и 31337 являются литералами.У них нет причин помещаться в стек.

Было бы более интересно, если бы вы распечатали разборку этого блока кода, чтобы точно узнать, что генерирует компилятор.Затем вы можете перепроверить, что содержится в вашем стеке во время выполнения.

Учитывая, что ваша функция не имеет побочных эффектов, она может быть оптимизирована до неактивности.

Вот что я получаюс вашим кодом в среде, с которой я более знаком:

Breakpoint 1, test_function (a=1, b=2, c=3, d=4) at t.c:4
4     flag = 31337;
(gdb) disass test_function
Dump of assembler code for function test_function:
   0x080483a4 <+0>: push   %ebp
   0x080483a5 <+1>: mov    %esp,%ebp
   0x080483a7 <+3>: sub    $0x10,%esp
=> 0x080483aa <+6>: movl   $0x7a69,-0x4(%ebp)
   0x080483b1 <+13>:    movb   $0x41,-0xe(%ebp)
   0x080483b5 <+17>:    leave  
   0x080483b6 <+18>:    ret    
End of assembler dump.
(gdb) display $ebp
2: $ebp = (void *) 0xffffcd70
(gdb) display $esp
3: $esp = (void *) 0xffffcd60
(gdb) x/16xw $esp
0xffffcd60: 0xf7e7dcdd  0xf7fa7324  0xf7fa6ff4  0x00000000
0xffffcd70: 0xffffcd88  0x080483e1  0x00000001  0x00000002
0xffffcd80: 0x00000003  0x00000004  0xffffcdf8  0xf7e66cc6
0xffffcd90: 0x00000001  0xffffce24  0xffffce2c  0x00000001

Разница в вашем случае, за исключением синтаксиса ASM, заключается в том, что мой компилятор зарезервировал меньше стека, но это все.

Итак, как и в вашем случае, литералы попадают в поток инструкций , а не в стек.Адрес стека и содержимое (интерпретируемое как 32-битные целые, осторожно с порядком байтов) локальных:

(gdb)  x/1xw $ebp-4
0xffffcd6c: 0x00000000
(gdb)  x/1xw $ebp-0xe
0xffffcd62: 0x7324f7e7

Теперь давайте присвоим flag:

(gdb) n
5     buffer[0] = 'A';
(gdb) x/8xw $esp
0xffffcd60: 0xf7e7dcdd  0xf7fa7324  0xf7fa6ff4  0x00007a69
0xffffcd70: 0xffffcd88  0x080483e1  0x00000001  0x00000002
(gdb)  x/1xw $ebp-4
0xffffcd6c: 0x00007a69
(gdb)  x/1xw $ebp-0xe
0xffffcd62: 0x7324f7e7

Все хорошо, верноСлот стека был обновлен ($ebp-4 последний 32-битный слот в строке 1 x / 8xw).

И позволяет установить первый элемент buffer:

(gdb) n
6   }
(gdb)  x/4x $ebp-0xe
0xffffcd62: 0x41    0xf7    0x24    0x73
(gdb) x/8xw $esp
0xffffcd60: 0xf741dcdd  0xf7fa7324  0xf7fa6ff4  0x00007a69
0xffffcd70: 0xffffcd88  0x080483e1  0x00000001  0x00000002
(gdb)  x/1xw $ebp-4
0xffffcd6c: 0x00007a69
(gdb)  x/1xw $ebp-0xe
0xffffcd62: 0x7324f741

Все хорошо снова,Порядковый порядок делает вещи немного странными, если их рассматривать как 32-битные целые, но выглядит хорошо, если смотреть на них побайтно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...