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?