Чтобы лучше понять бинарные файлы, я подготовил небольшой пример 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;
}
Проект скомпилирован с g ++ с сохранением отладочной информации. Далее 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 байта. Но похоже, что значения помещаются в стек без перемещения указателя стека.
Что я не правильно понял? Это проблема с компилятором или ассемблер пропустил некоторые строки?
С наилучшими пожеланиями,
ноль
Там нет абсолютно никаких проблем с вашим компилятором. Компилятор свободен выбирать, как компилировать ваш код, и он решил не изменять указатель стека. В этом нет необходимости, поскольку ваша функция не вызывает никаких других функций. Если бы он вызывал другую функцию, то ему нужно было бы создать еще один кадр стека, чтобы вызываемый не давил на стек стека вызывающего.
Как правило, вы не должны пытаться делать какие-либо предположения о том, как компилятор будет компилировать ваш код. Например, ваш компилятор может свободно оптимизировать тело вашей функции.
Других решений пока нет …