Эй,
Я написал эту очень простую основную функцию, чтобы поэкспериментировать с дизассемблированием, а также увидеть и, надеюсь, понять, что происходит на нижнем уровне:
int main() {
return 6;
}
Использование gdb для disas main дает следующее:
0x08048374 <main+0>: lea 0x4(%esp),%ecx
0x08048378 <main+4>: and $0xfffffff0,%esp
0x0804837b <main+7>: pushl -0x4(%ecx)
0x0804837e <main+10>: push %ebp
0x0804837f <main+11>: mov %esp,%ebp
0x08048381 <main+13>: push %ecx
0x08048382 <main+14>: mov $0x6,%eax
0x08048387 <main+19>: pop %ecx
0x08048388 <main+20>: pop %ebp
0x08048389 <main+21>: lea -0x4(%ecx),%esp
0x0804838c <main+24>: ret
Вот мое лучшее предположение о том, что, по моему мнению, происходит и в чем мне нужна помощь, построчно:
lea 0x4(%esp),%ecx
Загрузите адрес esp+4 в ecx. Почему мы добавляем 4 к esp?
Я где-то читал, что это адрес аргументов командной строки. Но когда я сделал x/d $ecx
, я получил значение argc. Где хранятся фактические значения аргументов командной строки?
and $0xfffffff0,%esp
Выровнять стек
pushl -0x4(%ecx)
Поместите адрес того места, где изначально находился esp, в стек. Какова цель этого?
push %ebp
Вставьте базовый указатель в стек
mov %esp,%ebp
Переместите текущий указатель стека в базовый указатель
push %ecx
Поместите адрес оригинального esp + 4 в стек. Почему?
mov $0x6,%eax
Я хотел вернуть 6 здесь, поэтому я предполагаю, что возвращаемое значение хранится в eax?
pop %ecx
Восстановите ecx до значения, которое находится в стеке. Почему мы хотим, чтобы ecx был равен esp + 4, когда мы возвращаемся?
pop %ebp
Восстановить ebp до значения, которое находится в стеке
lea -0x4(%ecx),%esp
Восстановить esp до исходного значения
ret
Я ноль, когда дело доходит до сборки, так что любая помощь будет здорово! Кроме того, если вы видите какие-либо ложные заявления о том, что, по моему мнению, происходит, пожалуйста, поправьте меня.
Огромное спасибо! :]