I have been given this code in C and I need to calculate the bytes allocated to the stack frame of function arith. I looked everywhere for a way to do it but everyone has a different answer.
long arith(long x, long y, long z){
long t1 = x + y;
long t2 = z + t1;
long t3 = x + 4;
long t4 = y * 48;
long t5 = t3 + t4;
long rval = t2 * t5;
return rval;
}
arith:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -56(%rbp)
movq %rsi, -64(%rbp)
movq %rdx, -72(%rbp)
movq -56(%rbp), %rdx
movq -64(%rbp), %rax
addq %rdx, %rax
movq %rax, -48(%rbp)
movq -72(%rbp), %rdx
movq -48(%rbp), %rax
addq %rdx, %rax
movq %rax, -40(%rbp)
movq -56(%rbp), %rax
addq $4, %rax
movq %rax, -32(%rbp)
movq -64(%rbp), %rdx
movq %rdx, %rax
addq %rax, %rax
addq %rdx, %rax
salq $4, %rax
movq %rax, -24(%rbp)
movq -32(%rbp), %rdx
movq -24(%rbp), %rax
addq %rdx, %rax
movq %rax, -16(%rbp)
movq -40(%rbp), %rax
imulq -16(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
I tried to add up the bytes every time we call the datatype long so 6*8, which is 64 bytes but im not very sure about this.
TL:DR: no, you can't tell just from looking at the C.
You need to look at the asm for a particular build and count push
es as well as sub $imm, %rsp
.
In this case, the variables aren't volatile
so a normal build (with optimization enabled) would just use registers, not touching the stack pointer at all. (You could say that the variables had their addresses optimized away, since they didn't escape the function, and nothing even took their addresses in the first place.)
See it yourself on Godbolt with GCC13 -O3 -fverbose-asm
# first set of comments is compiler-generated, second are hand-written
arith:
lea rax, [rsi+rsi*2] # t4, # RAX = y*3
sal rax, 4 # tmp96, # t4 = RAX = y*3*16 = y*48
lea rax, [rdi+4+rax] # t5, # t5 = RAX += x+4
add rdi, rsi # t1, y # t1 = x + y (replacing x in RDI)
add rdi, rdx # t2, tmp102 # t2 = x+y + z
imul rax, rdi # rval, t2 # rval = t5 * t2
ret
If optimization is disabled (Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?), you can calculate a minimum from the sizeof()
and alignof()
for the named C variables (assuming optimal packing), but compilers might reserve more for various reasons, like to align RSP, or
In a leaf function in the x86-64 System V ABI, the compiler can just use the space already reserved (the red zone) for some/all of the space it needs, so it might appear that less is needed: