Может кто-нибудь объяснить код сборки, пожалуйста? - PullRequest
3 голосов
/ 20 апреля 2011

Новое в сборке.У меня есть следующая функция

int foo(char *argv[])
{
   char buf[256];
   bar(argv[1], buf);
}

Что в сборке -

0x08048473 <foo+0>:push   %ebp
0x08048474 <foo+1>:mov    %esp,%ebp
0x08048476 <foo+3>:sub    $0x118,%esp
0x0804847c <foo+9>:mov    0x8(%ebp),%eax
0x0804847f <foo+12>:add    $0x4,%eax
0x08048482 <foo+15>:mov    (%eax),%edx
0x08048484 <foo+17>:lea    -0x100(%ebp),%eax
0x0804848a <foo+23>:mov    %eax,0x4(%esp)
0x0804848e <foo+27>:mov    %edx,(%esp)
0x08048491 <foo+30>:call   0x8048454 <bar>
0x08048496 <foo+35>:leave  
0x08048497 <foo+36>:ret    

Может кто-нибудь объяснить мне, пожалуйста?Почему там есть саб 280?256 байтов выделены в стеке обязательно.Я не могу объяснить остальное.

1 Ответ

4 голосов
/ 20 апреля 2011

Стек используется для локальных переменных, но также и для промежуточных значений, которые нужны функции.Здесь ваша foo() функция вызывает bar(), присваивая ей два указателя, один для строки (argv[1]), а другой для переменной buf;эти значения указателя помещаются в стек, а именно в коды операций mov %eax,0x4(%esp) и mov %edx,(%esp).Таким образом, foo() требуется чуть более 256 байтов стекового пространства.

Более подробно:

0x08048473 <foo+0>:push   %ebp
0x08048474 <foo+1>:mov    %esp,%ebp

Это стандартный пролог функции: функция будет использовать %ebp для точекэлементам стека до его вызова (т.е. его аргументов).

0x08048476 <foo+3>:sub    $0x118,%esp

Некоторое пространство в стеке зарезервировано, главным образом (но не только) для buf[].

0x0804847c <foo+9>:mov    0x8(%ebp),%eax
0x0804847f <foo+12>:add    $0x4,%eax
0x08048482 <foo+15>:mov    (%eax),%edx

0x8(%ebp) - аргумент функции argv;эти коды операций извлекают указатель из argv[1] и сохраняют результат в %edx.Это станет первым аргументом для bar().

0x08048484 <foo+17>:lea    -0x100(%ebp),%eax

. Сохраняет в %eax адрес buf[] - компилятор решил, что buf[] должен находиться в верхних 256 байтах.пространства стека, зарезервированного с помощью sub.

0x0804848a <foo+23>:mov    %eax,0x4(%esp)
0x0804848e <foo+27>:mov    %edx,(%esp)

Два аргумента для bar() помещаются в стек (фактически, записанные в двух верхних позициях стека, %esp уже настроены).

0x08048491 <foo+30>:call   0x8048454 <bar>

bar() вызывается.

0x08048496 <foo+35>:leave  
0x08048497 <foo+36>:ret

leave отменяет пролог (это эквивалентно mov %ebp, %esp; pop %ebp).ret выходит из функции.

Известно, что GCC перераспределяет бит в стеке;здесь он мог бы зарезервировать 264 байта вместо 280. Это, кажется, артефакт его внутреннего оптимизатора распределения регистров (дополнительные слоты стека были использовались для хранения промежуточных значений, но оптимизатор наконец нашел способы сохранитьтолько соответствующие значения в регистрах).

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