почему вычитается 32?
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movsd %xmm0, -24(%rbp)
movsd %xmm1, -32(%rbp)
movsd -32(%rbp), %xmm0
subsd -24(%rbp), %xmm0
movsd %xmm0, -8(%rbp)
movsd .LC0(%rip), %xmm0
divsd -8(%rbp), %xmm0
movsd %xmm0, -16(%rbp)
int callee(int, int, int);
int caller(void)
{
return callee(1, 2, 3) + 5;
}
On x86, it might produce the following assembly code (Intel syntax):
caller:
; make new call frame
; (some compilers may produce an 'enter' instruction instead)
push ebp ; save old call frame
mov ebp, esp ; initialize new call frame
; push call arguments, in reverse
; (<b>some compilers may subtract the required space from the stack pointer,
; then write each argument directly, see below.
; The 'enter' instruction can also do something similar)
; sub esp, 12 : 'enter' instruction could do this for us</b>
; mov [ebp-4], 3 : or mov [esp+8], 3
; mov [ebp-8], 2 : or mov [esp+4], 2
; mov [ebp-12], 1 : or mov [esp], 1
push 3
push 2
push 1
call callee ; call subroutine 'callee'
add esp, 12 ; remove call arguments from frame
add eax, 5 ; modify subroutine result
; (eax is the return value of our callee,
; so we don't have to move it into a local variable)
; restore old call frame
; (some compilers may produce a 'leave' instruction instead)
mov esp, ebp ; most calling conventions dictate ebp be callee-saved,
; i.e. it's preserved after calling the callee.
; it therefore still points to the start of our stack frame.
; we do need to make sure
; callee doesn't modify (or restore) ebp, though,
; so we need to make sure
; it uses a calling convention which does this
pop ebp ; restore old call frame
ret ; return