Я пытался глубже понять, как компиляторы генерируют машинный код, и более конкретно, как GCC работает со стеком. При этом я писал простые программы на Си, собирал их в ассемблер и старался изо всех сил понять результат. Вот простая программа и вывод, который она генерирует:
asmtest.c
* * 1004
void main() {
char buffer[5];
}
asmtest.s
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leave
ret
Что меня удивляет, так это то, почему для стека выделяется 24 байта. Я знаю, что из-за того, как процессор обращается к памяти, стек должен выделяться с шагом 4, но если бы это было так, мы должны перемещать указатель стека только на 8 байтов, а не 24. Для справки: буфер 17 в байтах создается указатель стека, перемещенный на 40 байтов, и ни один буфер вообще не перемещает указатель стека 8. Буфер между 1 и 16 байтами включительно перемещается ESP
24 байта.
Теперь, предполагая, что 8 байтов является необходимой константой (для чего она нужна?), Это означает, что мы выделяем порциями по 16 байтов. Почему компилятор будет выравнивать таким образом? Я использую процессор x86_64, но даже для 64-битного слова требуется только 8-байтовое выравнивание. Почему расхождение?
Для справки, я собираю это на Mac под управлением 10.5 с gcc 4.0.1 и без оптимизации.