使用帧指针MIPS

时间:2014-04-12 23:55:35

标签: assembly mips spim qtspim

我需要将我的代码从堆栈指针转换为仅使用帧指针,我该怎么办?我是MIPS的新手。

我在下面有这个递归C代码及其MIPS代码。我正在使用堆栈指针,如何更改它以使用帧指针?

这是我的C代码

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);
    }
  

这里是我的MIPS代码

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 个答案:

答案 0 :(得分:5)

我发现@markgz的评论很有意思。他与维基百科的链接包括引用:

  

帧指针($ 30)是可选的,实际上很少使用,除非在运行时确定函数中的堆栈分配,例如,通过调用alloca()。

我总是觉得$fp似乎是多余的,但无论如何我总是使用它,因为这就是我被教导的方式。

无论如何,如果你仍然感兴趣,这就是我使用帧指针的方式:

#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

所以每次扩展堆栈时,我都会使用堆栈指针来保存帧指针的旧值,然后在收缩堆栈时恢复帧指针的旧值。

大多数情况下,我每次编写新函数时都会复制并粘贴此代码。

答案 1 :(得分:2)

你应该从不转换MIPS代码以使用Frame Pointer而不是堆栈指针,因为这会违反MIPS Calling Convention,并且您的代码将停止与其他代码一起使用人们的代码。

帧指针通常不用于手动编码的MIPS汇编程序,因为堆栈指针在执行函数期间不会更改值。实际上,您自己的代码已正确编码,因此堆栈指针永远不会更改值。

答案 2 :(得分:0)

扩展Konrad Lindenbach的回答:

#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
lw $fp, 0($fp)

ja $ra

这种方式更容易读写,而不会牺牲指令长度。您也可以将此方法用于动态内存分配,因为恢复代码段不需要知道已为堆栈分配了多少数据。