Assembly MIPS-未返回预期结果

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

我刚开始学习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

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

抱歉,我编辑了你的答案,我才意识到这是我的错。我在你的新代码上添加了一些注释。