Создание пространства для локальных переменных в сборке

Так что мне нужно написать программу на ассемблере, которая вызывала бы функцию extern C. Итак, я написал простой pow Функция, я скомпилировал мою программу сборки с этим кодом C. Все работает. Но как я видел из -S команда от gccкомпилятор создает пробел для локальных переменных. Я думал, что это будет так:

int func(int number)
{
    int a = 10;
    int b = 5;
    int c = 0;
}

У нас есть 3 локальные переменные, поэтому компилятор будет subl $12, %esp, Но это идет для subl $16, %esp, Даже если бы я оставил здесь только одно число, оно все равно уменьшилось бы на 16, Теперь у меня есть мой код:

main.s:

.section .data
.XD:
    msg: .ascii "%d\n"
    msg_len = . - msg

.text
.globl _pow
.globl main

main:
    pushl   %ebp
    movl    %esp, %ebp
    movl $5, %eax #like int a = 5;
    pushl %eax 
    call _pow #_pow(a);
    movl %eax, -8(%ebp)
    pushl -8(%ebp)
    pushl $.XD
    call printf #printf("%d\n", _pow(a));
    movl $0, %eax
    leave
    ret

func.c:

int _pow(int number)
{
    return number * number;
}

Работает как положено, ./main распечатывает 25, Но сейчас я не subl что-нибудь из %esp, Я имею в виду, я могу добавить эту строку, но это ничего не меняет. Я искал в интернете, и я обнаружил, что, возможно, мой код работает просто случайно, и, как правило, я должен уменьшить %esp, Итак, мой вопрос здесь: на какую величину я должен уменьшить %esp в main? Должно ли это быть 12 или, может быть 16?

1 ответ

Решение

Поскольку вы вызываете 32-битную функцию C, вы должны следовать соглашению о вызовах C. В отличие от 64-битных систем, здесь нет явного порядка выравнивания стека. Я не мог найти утверждение, когда такое выравнивание должно произойти. Стек может быть "выровнен" после нажатия параметров.

Если вы хотите выровнять стек, вы можете просто AND -16 после того, как вы сохранили его (movl %esp, %ebp):

andl $-16, %esp                ; Align 16
Другие вопросы по тегам