Это код c:
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);
}
Сборка 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: (1)0x00000000 0x08049548 0xbffff7d8 0x08048249
0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9
0xbffff7e0: 0xb7fd6ff4 (2)0xbffff89c (3)0xbffff808 (4)0x0804838b
0xbffff7f0: (5)0x00000001 0x00000002 0x00000003 0x00000004
Я новичок в этих темах; поэтому в голове есть некоторые вопросы.





Вы проблема
It pushes ebp, then copies esp to ebt
ebt неверен, нет регистра, вызывающего ebt. Это должно быть ebp.
push ebp
команда предназначена для сохранения дна стека перед вызовом функции test_function.
mov ebp,esp
sub esp,0x28
команда предназначена для увеличения стека, чтобы выделить новый блок памяти для хранения значений во время выполнения функции test_function. А размер увеличения стека не фиксирован и не всегда будет 0x28. Это значение рассчитывается компилятором, который гарантирует, что размер подходит.
mov DWORD PTR [ebp-12],0x7a69
соответствует флагу = 31337, адрес флага равен значению ebp-12. Адрес назначается компилятором. DWORD соответствует int. Шестнадцатеричное число 0x7a69 эквивалентно десятичному числу 31337.
И
mov BYTE PTR [ebp-40],0x41
такой же как. Шестнадцатеричное число 0x41 эквивалентно десятичному числу 65. Десятичное значение кода ASCII для буквы A — это десятичное число 65. BYTE соответствует char.
Ниже код
(gdb) x/16xw $esp
0xbffff7c0: (1)0x00000000 0x08049548 0xbffff7d8 0x08048249
0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9
0xbffff7e0: 0xb7fd6ff4 (2)0xbffff89c (3)0xbffff808 (4)0x0804838b
0xbffff7f0: (5)0x00000001 0x00000002 0x00000003 0x00000004
Например, 0xbffff7c0: левый код — это адрес, его значение равно 0x00000000. Таким образом, значение адреса 0xbffff7c4(0xbffff7c4 = 0xbffff7c0 + 4) равно 0x08049548, потому что 0x00000000 занимает 4 байта. Значение адреса 0xbffff7c8 равно 0xbffff7d8. ....
Я думаю ниже код ассемблера
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
можно преобразовать приведенный ниже код (поскольку @Peter Cordes указывает, что «leave» равно «mov esp,ebp» + «pop ebp», см. https://www.felixcloutier.com/x86/leave)
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
mov esp,ebp // here changed
pop ebp // here changed
0x08048356 <test_function+18>: ret
Таким образом, мы можем получить изображение, см. ниже:
leave делает то же самое, что и mov ebp, esp / pop ebp (felixcloutier.com/x86/leave). GCC использует его, потому что это меньший машинный код. (На процессорах Intel это стоит еще одну операцию, но при оптимизации скорости большинство функций не будут использовать EBP в качестве указателя кадра.)
@PeterCordes Спасибо за исправление. Я изменил свой ответ.
Еще один вопрос. Разве esp не является указателем, как переход к памяти выделяет память по пути? Саб так делает или это специально для esp?
@steatoda Извините, мой родной язык не английский, поэтому, возможно, я неточно использовал слово «распределяет». esp - это указатель стека. Локальные переменные хранятся в стеке. Саб так делает или это специально для esp? Ответ под, смотрите картинку в моем ответе в последнем разделе.
1) это 40 байт, а не бит. Это пространство, выделенное для локальных переменных. 2) Потому что компилятор решил разместить там
flag. Непонятно, в какой момент вы остановили программу для создания дампа. 3) Я не понимаю вопроса, но это просто дамп памяти с адресами и значениями.