2013-02-27 2 views
3

Чтобы лучше понять бинарные файлы, я подготовил небольшой пример C++ и использовал gdb для демонтажа и поиска машинного кода.Уменьшение указателя стека путем создания локальных переменных

main() функция вызывает функцию func():

int func(void) 
{ 
    int a; 
    int b; 
    int c; 
    int d; 
    d = 4; 
    c = 3; 
    b = 2; 
    a = 1; 
    return 0; 
} 

Проект компилируется с г ++ хранение информации об отладке. Следующий gdb используется для демонстрации исходного кода. То, что я получил за func() выглядит следующим образом:

0x00000000004004cc <+0>: push %rbp 
0x00000000004004cd <+1>: mov %rsp,%rbp 
0x00000000004004d0 <+4>: movl $0x4,-0x10(%rbp) 
0x00000000004004d7 <+11>: movl $0x3,-0xc(%rbp) 
0x00000000004004de <+18>: movl $0x2,-0x8(%rbp) 
0x00000000004004e5 <+25>: movl $0x1,-0x4(%rbp) 
0x00000000004004ec <+32>: mov $0x0,%eax 
0x00000000004004f1 <+37>: pop %rbp 
0x00000000004004f2 <+38>: retq 

Теперь моя проблема заключается в том, что я ожидаю, что указатель стека должен быть перемещен на 16 байт, чтобы понизить адреса относительно базового указателя, так как каждое целое значение должно 4 байта. Но похоже, что значения помещаются в стек, не перемещая указатель стека.

Что я не понял правильно? Это проблема с компилятором, или ассемблер опустил некоторые строки?

С наилучшими пожеланиями,
напрасными

+0

Какой-то компилятор ничего не сделал, кроме возврата 0. – QuentinUK

+0

Вы пытались скомпилировать с '-O3'? – Walter

+0

У меня как-то возникает ощущение, что ваше понимание «указателя инструкций» не совпадает с моим. – PlasmaHH

ответ

4

Там нет абсолютно никаких проблем с компилятором. Компилятор может свободно выбирать, как скомпилировать ваш код, и он решил не изменять указатель стека. Нет необходимости в этом, так как ваша функция не вызывает никаких других функций. Если бы он вызывал другую функцию, тогда ему понадобилось бы создать еще один фрейм стека, чтобы вызываемый не топал в стеке стека вызывающего.

Как правило, вам следует избегать попыток сделать какие-либо предположения о том, как компилятор будет компилировать ваш код. Например, ваш компилятор будет совершенно свободен, чтобы опровергнуть тело вашей функции.

+0

Спасибо, именно в этом смысл. После вызова дополнительной функции все выглядит так, как ожидалось. – NouGHt

+2

@NouGHt: Все как и ожидалось. Базовый указатель ('% rbp') сохраняется для последующего восстановления в верхней части стека. '% rbp' затем имеет старую вершину стека, загруженную в нее. Затем доступ к стеку осуществляется с использованием адресов относительно '% rbp' и устанавливаются все локальные переменные. Наконец, базовый указатель возвращается к исходному значению, а '0' возвращается в'% eax'. Указатель стека не изменяется, потому что код не содержит ничего, что могло бы сбивать локальные переменные, поэтому нет необходимости связывать свои позиции с другим кодом, устанавливая указатель стека на некоторое значение. – Mankarse

Смежные вопросы