как новичок asm, я проверяю, что gcc-S сгенерировал код asm для изучения.
почему gcc 4.x значение по умолчанию резервируют 8 байтов для стека при вызове метода?
func18 является пустой функцией без возврата никакой параметрический усилитель никакой локальный определенный var. Я не могу выяснить, почему 8 байтов резервируются здесь (никакое любое упоминание форума/сайта по причине, люди кажется, принимают как очевидное), это для %ebp, просто продвигают? или возвратите тип?! большое спасибо!
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
.text
Простой способ узнать: у вас пустая функция вызывает другую функцию с одним параметром. Если параметр хранится непосредственно в стеке (без проталкивания), то для этого нужно дополнительное пространство.
Как Ричард упомянул выше, это все из-за оптимизации, показанной ниже. но я все еще не понимаю, почему зарезервированные 8 байтов - это что-то оптимизированное ?!
исходный c
void func18() {}
int main() {return 0;}
компилируется без указанного флага оптимизации
.text
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
leave
ret
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $0, %eax
leave
ret
.subsections_via_symbols
с флагом оптимизации -Os, без резерва стека
.text
.globl _func18
_func18:
pushl %ebp
movl %esp, %ebp
leave
ret
.globl _main
_main:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
leave
ret
.subsections_via_symbols
Некоторые инструкции требуют выравнивания определенных типов данных по 16-байтовой границе (в частности, SSE-тип данных __m128). Чтобы удовлетворить это требование, gcc гарантирует, что стек изначально выровнен по 16 байтам, и выделяет пространство стека кратно 16 байтам. Если нужно переместить только 4-байтовый адрес возврата и 4-байтовый указатель кадра, то для выравнивания стека по 16-байтовой границе требуется 8 дополнительных байт. Однако если gcc определит, что дополнительное выравнивание не нужно (т.е. не используются причудливые типы данных и не вызываются внешние функции), то он может опустить все дополнительные инструкции, используемые для выравнивания стека. Анализ, необходимый для определения этого, может потребовать выполнения определенных проходов оптимизации.
См. также документацию gcc для опции -mpreferred-stack-boundary=num.