Let's take the following basic C function and the intentionally unoptimized assembly it produces:
int main() {
int i = 4;
return 3;
}
It produces the following (unoptimized) assembly, which all makes sense to me:
main:
pushq %rbp
movq %rsp, %rbp
movl $4, -4(%rbp)
movl $3, %eax
popq %rbp
ret
However, as soon as I add in a function call, there are two instructions that I don't quite understand:
void call() {};
int main() {
int i = 4;
call();
return 3;
}
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp <-- why is it subtracting 16?
movl $4, -4(%rbp)
movl $0, %eax <-- why is it first clearing the %eax register?
call call
movl $3, %eax
leave
ret
If the stackframe needs to be 16-byte aligned, how does the subq $16, %rsp
help with that? Doesn't the initial pushq %rbp
instruction already offset it by 8 and now it's at +24 ? Or what are the points of those two lines in question above?