Создание пространства для локальных переменных в сборке
Так что мне нужно написать программу на ассемблере, которая вызывала бы функцию 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