Assembly MIPS-未返回预期结果
我刚开始学习MIPS,我正在尝试将一个用C编写的递归程序翻译成MIPS,我遇到了一些问题 C语言的程序如下:Assembly MIPS-未返回预期结果,assembly,mips,Assembly,Mips,我刚开始学习MIPS,我正在尝试将一个用C编写的递归程序翻译成MIPS,我遇到了一些问题 C语言的程序如下: int calculate (int n, int k){ int b; b = k+2; if (n == 0) b = 10; else b = b + 8*n + calculate (n-1,k+1); return b*k; } 这是我在MIPS中编写的程序: main: addi $a0,$0,2 addi $a1,$0,3
int calculate (int n, int k){
int b;
b = k+2;
if (n == 0)
b = 10;
else
b = b + 8*n + calculate (n-1,k+1);
return b*k;
}
这是我在MIPS中编写的程序:
main:
addi $a0,$0,2
addi $a1,$0,3
jal calculate
addi $t3,$v0,0
li $v0,10
syscall
calculate:
#a0 = n, a1 = k, t0 = b
addiu $sp,$sp,-12
sw $a0,0($sp) # save a0 to stack
sw $a1,4($sp) # save a1 to stack
sw $ra,8($sp) # save return address to stack
# Base case
bne $a0,$0,else # n!=0
li $t0,10 # b = 10
mul $v0,$t0,$a1 # v0 = b*k
j return # Go to Return
else:
addi $a0,$a0,-1 # n - 1
addi $a1,$a1,1 # k + 1
jal calculate
add $t0,$t0,$v0 # b += calculate(n-1,k+1)
lw $a0,0($sp) # Retrive the original n
lw $a1,4($sp) # Retrieve the original k
addi $t0,$a1,2 # b += k+2
li $t1,8 # load 8 as constant
mul $t1, $t1,$a0 # 8*n
add $t0,$t0,$t1 # b = b + 8*n
mul $v0,$t0,$a1 # v0 = b*k
return:
lw $a0,0($sp) # retrive a0 from stack
lw $a1,4($sp) # retreive a1 from stack
lw $ra,8($sp) # retrive return address to stack
addiu $sp,$sp,12
jr $ra
我正在使用MARS模拟器,它显示我的结果寄存器$t3的值为0x384,十进制为900。当我用C运行程序时,结果是831
然而,我觉得一切都很好,我觉得我的程序应该运行正常
我的程序还有其他问题吗?在MIPS中编写递归程序对我来说确实有点复杂。在(递归)调用之前,您正在计算k+2+8*n,这在理论上是很好的-但在调用过程中将结果保留在
$t0
中并不合适,因为它将被调用清除
您有两个选择:
- 在调用之前保存
(在计算该子表达式和之后),并在调用之后恢复它。$t0
如果这样做,您将需要另一个字的堆栈空间(但您也不需要真正保存
(n
),因为调用后不使用它)$a0
- 在调用后计算k+2+8*n,这将不需要额外的字堆栈空间,但这将利用调用后保存的
(n
)$a0
在prolog中保存参数寄存器时,它们不需要在尾声中还原,因此只需还原
$ra
即可返回
使用addiu
进行堆栈分配/解除分配。地址算法应该使用unsigned完成。(注意addi
和addiu
之间的唯一区别是addi
检查有符号算术中的溢出,我们不希望地址b/c有符号。)
在最新编辑中:
jal calculate
add $t0,$t0,$v0 # b += calculate(n-1,k+1) #### $t0 not good to source here
lw $a0,0($sp) # Retrive the original n
lw $a1,4($sp) # Retrieve the original k
addi $t0,$a1,2 # b += k+2
建议先执行b=k+2
:
jal calculate
lw $a0,0($sp) # Retrive the original n
lw $a1,4($sp) # Retrieve the original k
addi $t0,$a1,2 # b = k+2 ##### b=k+2 do that first
add $t0,$t0,$v0 # b += calculate(n-1,k+1) ##### now b += will work
抱歉,我编辑了你的答案,我才意识到这是我的错。我在你的新代码上添加了一些注释。