You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS汇编实现卡特兰数递归算法出错,请求问题定位与修正

卡特兰数递归MIPS汇编代码错误修正

测试用例

Program input:
0 1 2 3 6 9 
Expected output:
1 1 2 5 132 4862 
Obtained output:
1 1 2 4 32 256   

可见当n=3时,预期输出为5,实际输出为4,后续结果全部错误,问题出在循环计算部分,以下是错误代码及修正方案:

错误的MIPS汇编代码

catalan_recur:
addi $sp,$sp,-12
sw $ra,0($sp)
sw $s0,4($sp)
sw $a0,8($sp)
addi $t0,$0,1

bgt $a0,$t0,catalan_recur_else     #a0>1 ?
li $v0, 1
lw $s0, 4($sp)
lw $ra, 0($sp)
addiu $sp, $sp, 12
jr $ra

catalan_recur_else:
  li $t1,0         #res=0
  li $t2,0         #i=0
catalan_recur_loop:  
  bge $t2, $a0, end_loop  # if i >= n, exit loop
   # res += catalan_recur(i)*catalan_recur(n-i-1)
  move $a0, $t2              
  jal catalan_recur          # call catalan_recur(i)        
  add $s0,$0,$v0             # get return value and store in $s0
  lw $a0,8($sp)
  addi $t2,$t2,1             # i++
  sub $a0,$a0,$t2            # calculate n-i-1
  jal catalan_recur          # call catalan_recur(n-i-1)
  mult $s0,$s0,$v0           # catalan_recur(i) * catalan_recur(n-i-1)
  add $t1,$t1,$s0            # add to res
  lw $s0,4($sp)
  lw $a0,8($sp)
  j catalan_recur_loop  
        
end_loop:
  move $v0, $t1               # move res to $v0
  lw $a0,8($sp)
  lw $s0,4($sp)        
  lw $ra, 0($sp)
  addiu $sp, $sp, 12
jr $ra

对应伪代码

def catalan_recur(n):
    if n <= 1:
        return 1;
    else:
        res = 0
        for i in range(n):  # i = 0 ~ (n-1)
            res += catalan_recur(i) * catalan_recur(n-i-1)
         return res;

# a0: 输入的正整数参数n

错误分析与修正

1. 乘法指令使用错误

MIPS的mult指令仅接受两个寄存器操作数,且乘法结果存入hi和lo寄存器,原代码中mult $s0,$s0,$v0是非法语法,正确做法是用mult $s0, $v0,之后通过mflo取出低32位结果存入临时寄存器。

2. 循环中i的递增时机错误

原代码在调用catalan_recur(i)后立即执行i++,导致计算n-i-1时使用递增后的i值,与伪逻辑中n-i-1(i为当前循环值)不符,应先计算n-i-1再执行i++。

3. 累加结果时使用错误的寄存器

原代码将$s0(catalan_recur(i)的结果)直接累加,实际需要先取出乘法结果再累加到$t1。

4. 临时寄存器$t2的保存问题

MIPS中t系列寄存器属于临时寄存器,递归调用会破坏其值,因此需要将$t2(循环变量i)存入栈中保存,避免被递归调用覆盖。

修正后的MIPS汇编代码

catalan_recur:
addi $sp,$sp,-16          # 增加栈空间,用于保存$t2
sw $ra,0($sp)
sw $s0,4($sp)
sw $a0,8($sp)
sw $t2,12($sp)            # 保存循环变量i到栈中
addi $t0,$0,1

bgt $a0,$t0,catalan_recur_else     #a0>1 ?
li $v0, 1
lw $t2,12($sp)             # 恢复$t2
lw $s0, 4($sp)
lw $ra, 0($sp)
addiu $sp, $sp, 16
jr $ra

catalan_recur_else:
  li $t1,0         #res=0
  li $t2,0         #i=0
catalan_recur_loop:  
  bge $t2, $a0, end_loop  # if i >= n, exit loop
   # res += catalan_recur(i)*catalan_recur(n-i-1)
  move $a0, $t2              
  jal catalan_recur          # call catalan_recur(i)        
  move $s0, $v0             # 保存catalan(i)到$s0
  lw $a0,8($sp)             # 恢复原n值
  # 先计算n-i-1,再递增i
  sub $a0,$a0,$t2            # n - i
  addi $a0,$a0,-1            # n - i -1
  jal catalan_recur          # call catalan_recur(n-i-1)
  # 计算乘法:catalan(i)*catalan(n-i-1)
  mult $s0, $v0
  mflo $t3                   # 取出乘法结果到$t3
  add $t1,$t1,$t3            # 累加到res
  addi $t2,$t2,1             # i++,此时再递增
  lw $a0,8($sp)              # 恢复原n值,准备下一次循环
  j catalan_recur_loop  
        
end_loop:
  move $v0, $t1               # move res to $v0
  lw $t2,12($sp)             # 恢复$t2
  lw $a0,8($sp)
  lw $s0,4($sp)        
  lw $ra, 0($sp)
  addiu $sp, $sp, 16
jr $ra

验证

修正后,输入0 1 2 3 6 9将得到预期输出1 1 2 5 132 4862。

内容的提问来源于stack exchange,提问作者BeyongOn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:05:00