I am reading an introductory computer design book. The book explains the inner workings using MIPS, is very information dense and expects the reader to connect the dots.
This is the c code:
main ()
{
printf (“The factorial of 10 is %d\n”, fact (10));
}
int fact (int n)
{
if (n < 1)
return (1);
else
return (n * fact (n - 1));
}
And this is the first few lines of a mips assembly:
.text
.globl main
main:
subu $sp,$sp,32 # Stack frame is 32 bytes long
sw $ra,20($sp) # Save return address
sw $fp,16($sp) # Save old frame pointer
addiu $fp,$sp,28 # Set up frame pointer
The author states the following:
Upon entry, the routine main creates its stack frame and saves the two calleesaved registers it will modify: $fp and $ra. The frame is larger than required for these two register because the calling convention requires the minimum size of a stack frame to be 24 bytes. This minimum frame can hold four argument registers ($a0–$a3) and the return address $ra, padded to a double-word boundary (24 bytes). Since main also needs to save $fp, its stack frame must be two words larger (remember: the stack pointer is kept doubleword aligned).
My understanding is that positions 0,4,8 and 12 of the stack frame are reserved for $a0-$a3 registers. That is why the old $fp
is placed at 16 and $ra
is stored at 20(up to 23). That is 24 bytes total. 24 is doubleword aligned (double word aligned means that it is address%8 == 0 and 24%8 == 0, right?). Why is the stack 32 bytes if 24 matches the criterium of double word alignment? Also why does the frame pointer not start at old $sp
address, but at 4 bytes later? I feel like I am missing some additional information.