Why are the 7th and later arguments in C written to %rax?

Viewed 64

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.

0 Answers
Related