我需要将我的代码从堆栈指针转换为仅使用帧指针,我该怎么办?我是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
答案 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
这种方式更容易读写,而不会牺牲指令长度。您也可以将此方法用于动态内存分配,因为恢复代码段不需要知道已为堆栈分配了多少数据。