2
votes

i need to convert my code from stack pointer to only use frame pointer, how can i do so? i am very new to MIPS.

i have this recursion C code and its MIPS code below. i am using stack pointer , how can i change it to use frame pointer?

here is my C Code

int fact(int n)
{
    if(n!=1)
     return n*factorial(n-1);
}

    int comb (int n, int k)
    {
    return fact (n) / fact (k) / fact (n - k);
    }

here my MIPS code

comb:           
 sub $sp, $sp, 16
 sw $ra , 0($sp)
 sw $s0, 4($sp) 
 sw $a0, 8($sp) 
 sw $a1, 12($sp)
 jal fact       
 move $s0, $v0  
 lw $a0, 12($sp) 
 jal fact       
 div $s0, $s0, $v0 
 lw $a0, 8($sp) 
 lw $a1, 12($sp) 
 sub $a0, $a0, $a1 
 jal fact       
 div $s0, $s0, $v0 
 move $v0, $s0  
 lw  $ra, 0($sp) 
 lw  $s0, 4($sp) 
 addi $sp, $sp, 16 
 jr $ra         
3

3 Answers

6
votes

I found @markgz's comments to be interesting. His link to Wikipedia includes the quote:

The frame pointer ($30) is optional and in practice rarely used except when the stack allocation in a function is determined at runtime, for example, by calling alloca().

I always kinda thoght that $fp seemed superfluous, but I always used it anyway because that's how I was taught to do it.

Anyway, if you are still interested, here is how I used the frame pointer:

#save $ra $s0, $a0 on stack
addi $sp $sp -4
sw   $fp 0($sp)
move $fp $sp
addi $sp $sp -12
sw   $ra  -4($fp)
sw   $a0  -8($fp)
sw   $s0 -12($fp)

...

#restore and shrink stack
lw $s0 -12($fp)
lw $ra  -4($fp)
lw $fp   0($fp)
addi $sp $sp 16

jr $ra

So each time the stack is expanded, I use the stack-pointer to save the old value of the frame pointer, and then I restore the old value of the frame pointer when shrinking the stack.

Mostly I just copy and paste this code every time I write a new function.

2
votes

You should never convert MIPS code to use the Frame Pointer instead of the Stack Pointer, because that would violate MIPS Calling Convention, and your code would cease to work with other people's code.

The Frame Pointer is not typically used in hand coded MIPS assembler, because the stack pointer does not change value during the execution of a function. Indeed, your own code is correctly coded so that the stack pointer never changes value.

0
votes

Expanding on Konrad Lindenbach's answer:

#save $ra, $s0, $a0, $a1
addi $sp, $sp, -4
sw $fp, 0($sp)
move $fp, $sp
addi $sp, $sp, -16
sw $ra, -4($fp)
sw $a0, -8($fp)
sw $a1, -12($fp)
sw $s0, -16($fp)


#Your Code Here


#Restore
lw $s0, -16($fp)
lw $ra, -4($fp) #Can Be C+P'd from here down

addi $sp, $fp, 4 #restore $sp
lw $fp, 0($fp) #restore $fp

jr $ra #return to caller

This way is much easier to read and write without sacrificing instruction length. You would use this method for dynamic memory allocation too, as the restoration snippet does not need to know how much data was allocated to the stack.