I have the following C code:
#include <stdint.h>
int64_t otherthing()
{
return 42;
}
int64_t thing(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e, int64_t f, // registers
int64_t g, int64_t h, int64_t i, int64_t j) // caller stack
{
return otherthing() + a - c + g - j;
}
int64_t main()
{
return thing(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
Which compiles to, under x86-64 Clang 14.0.0 (Compiler Explorer), with no optimisations:
otherthing: # @otherthing
pushq %rbp
movq %rsp, %rbp
movl $42, %eax
popq %rbp
retq
thing: # @thing
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
movq 40(%rbp), %rax
movq 32(%rbp), %rax
movq 24(%rbp), %rax
movq 16(%rbp), %rax
movq %rdi, -8(%rbp)
movq %rsi, -16(%rbp)
movq %rdx, -24(%rbp)
movq %rcx, -32(%rbp)
movq %r8, -40(%rbp)
movq %r9, -48(%rbp)
callq otherthing
addq -8(%rbp), %rax
subq -24(%rbp), %rax
addq 16(%rbp), %rax
subq 40(%rbp), %rax
addq $48, %rsp
popq %rbp
retq
main: # @main
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl $1, %edi
movl $2, %esi
movl $3, %edx
movl $4, %ecx
movl $5, %r8d
movl $6, %r9d
movq $7, (%rsp)
movq $8, 8(%rsp)
movq $9, 16(%rsp)
movq $10, 24(%rsp)
callq thing
addq $32, %rsp
popq %rbp
retq
Now, I understand the first six arguments to thing, i.e. a to f, are saved in registers, and when thing is called, the assembly is such that the values of those registers are saved to the callee's (i.e. thing's) stack, according to the System V calling conventions.
However, what is the point in writing the 7th to 10th caller-stack-saved arguments—i.e. g to j—to %rax? To be clear, I'm referring to the the four movq <positive number>(%rbp), %rax instructions, immediately after subq $48, %rsp.