Настройка локального стека в соответствии с соглашением о вызовах 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 вариант.

Другие вопросы по тегам