Я должен был скомпилировать эту c программу, которая, как говорят, низкого качества, и помнить, что я использую старую виртуальную машину IA-32 с архитектурой. Эта программа большую часть времени возвращает ошибку сегментации, и я должен ее отладить. Я очень новичок в сборке, и я понимаю, что каждая инструкция делает на уровне стека, например, я знаю, что делают lea
, sub
, push
et c. Моя трудность заключается в том, чтобы понять, какой части моей программы C она соответствует и почему они выполняются.
Это программа:
char *getline() {
char buf[8];
char *result;
gets(buf);
result = malloc(strlen(buf));
strcpy(result, buf);
return result ;
}
void main () {
getline();
}
Я скомпилировал этот файл, используя gcc -O0 -g
, а затем использовал gdb
для этого исполняемого файла и разбирал getline
и main
по отдельности. Это вывод для getline
:
0x08048400 <getline+0>: push %ebp
0x08048401 <getline+1>: mov %esp,%ebp
0x08048403 <getline+3>: sub $0x18,%esp
0x08048406 <getline+6>: sub $0xc,%esp
0x08048409 <getline+9>: lea 0xfffffff8(%ebp),%eax
0x0804840c <getline+12>: push %eax
0x0804840d <getline+13>: call 0x8048304
0x08048412 <getline+18>: add $0x10,%esp
0x08048415 <getline+21>: sub $0xc,%esp
0x08048418 <getline+24>: lea 0xfffffff8(%ebp),%eax
0x0804841b <getline+27>: push %eax
0x0804841c <getline+28>: call 0x8048324
0x08048421 <getline+33>: add $0x4,%esp
0x08048424 <getline+36>: push %eax
0x08048425 <getline+37>: call 0x8048314
0x0804842a <getline+42>: add $0x10,%esp
0x0804842d <getline+45>: mov %eax,0xfffffff4(%ebp)
0x08048430 <getline+48>: sub $0x8,%esp
0x08048433 <getline+51>: lea 0xfffffff8(%ebp),%eax
0x08048436 <getline+54>: push %eax
0x08048437 <getline+55>: pushl 0xfffffff4(%ebp)
0x0804843a <getline+58>: call 0x8048344
0x0804843f <getline+63>: add $0x10,%esp
0x08048442 <getline+66>: mov 0xfffffff4(%ebp),%eax
0x08048445 <getline+69>: leave
0x08048446 <getline+70>: ret
main
:
0x08048447 <main+0>: push %ebp
0x08048448 <main+1>: mov %esp,%ebp
0x0804844a <main+3>: sub $0x8,%esp
0x0804844d <main+6>: and $0xfffffff0,%esp
0x08048450 <main+9>: mov $0x0,%eax
0x08048455 <main+14>: sub %eax,%esp
0x08048457 <main+16>: call 0x8048400 <getline>
0x0804845c <main+21>: leave
0x0804845d <main+22>: ret
Как я уже сказал, я понимаю саму сборку, я просто не понимаю цели всех инструкции. Первые две и две последние инструкции объяснять не нужно, потому что я понимаю. (Мне нужна только помощь с getline
сборкой, а не main
). Мои трудности в основном таковы:
1- sub
инструкции - я понимаю, что вы выделяете место в стеке, но почему это так много места и какой части кода C это соответствует к?
2- Что именно делает lea
? Он помещает значение в %eax
, каково значение этого значения и почему оно добавляется после, для сохранения?
3 - Все ли инструкции push
предназначены только для сохранения содержимого регистры перед вызовом функции или у них другое назначение?