Настройка локального стека в соответствии с соглашением о вызовах x86-64 в Linux
Я делаю некоторую расширенную оптимизацию сборки на коде gnu C, работающем на 64-битной Linux. Я хотел напечатать отладочные сообщения из кода сборки, и вот как я наткнулся на следующее. Я надеюсь, что кто-то может объяснить, что я должен делать в этой ситуации.
Взгляните на этот пример функции:
void test(int a, int b, int c, int d){
__asm__ volatile (
"movq $0, %%rax\n\t"
"pushq %%rax\n\t"
"popq %%rax\n\t"
:
:"m" (a)
:"cc", "%rax"
);
}
Поскольку четыре компонента функции относятся к классу INTEGER, они будут переданы через регистры и затем помещены в стек. Странно для меня то, как на самом деле это делает gcc:
test:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
movl %ecx, -16(%rbp)
movq $0, %rax
pushq %rax
popq %rax
popq %rbp
ret
Переданные аргументы помещаются в стек, но указатель стека не уменьшается. Таким образом, когда я делаю pushq %rax
, значения a
а также b
перезаписаны Что мне интересно: есть ли способ попросить gcc правильно настроить локальный стек? Я просто не должен использовать push
а также pop
в вызовах функций?
1 ответ
x86-64 abi предоставляет 128-байтовую красную зону под указателем стека, и компилятор решил использовать это. Вы можете отключить это с помощью -mno-red-zone
вариант.