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

MIPS汇编合并有序数组:循环异常、乱码及降序实现求助

问题修复与降序实现方案

一、打印无限循环&lw指令报错的根因与修复

核心问题

你的打印逻辑没有正确的终止条件,导致数组指针越界访问无效内存(lw $s0, 0($a2)的报错就是访问了未分配的内存地址),进而触发无限循环并输出乱码。常见的错误场景:

  • 用数组元素的某个特定值(比如0)作为终止标志,但原数组可能包含该值
  • 未正确计算合并后数组的总长度,循环计数器没有上限

修复步骤

  1. 提前计算合并后数组的总长度:将两个输入数组的长度相加,存入寄存器(比如$s3),作为循环终止的判断依据。
  2. 修正打印循环逻辑:用计数器和总长度比较,而非依赖元素值。示例代码片段:
# 假设合并后的升序数组基地址存在$a2,总长度存在$s3
move $t0, $zero       # 初始化计数器为0
print_loop:
bge $t0, $s3, end_print  # 计数器 >= 总长度时退出循环
lw $s0, 0($a2)        # 读取当前元素(此时$a2不会越界)

# 打印元素的代码(调用syscall打印整数)
li $v0, 1
move $a0, $s0
syscall

# 打印分隔符(逗号)
li $v0, 11
li $a0, ','
syscall

addi $a2, $a2, 4      # 指针移动到下一个整数
addi $t0, $t0, 1      # 计数器自增
j print_loop
end_print:

二、降序输出的实现方案

有两种简单可行的实现方式:

方式1:反转升序数组

在完成升序合并后,直接反转升序数组得到降序结果,适合逻辑简单的场景:

# 假设升序数组基地址为$a2,总长度为$s3
move $t0, $zero       # 左指针(从数组头部开始)
addi $t1, $s3, -1     # 右指针(从数组尾部开始)
sll $t1, $t1, 2       # 转换为字节偏移(每个整数4字节)
add $t1, $t1, $a2

reverse_loop:
bge $t0, $t1, end_reverse  # 左右指针相遇时停止
# 交换左右指针指向的元素
lw $t2, 0($t0)
lw $t3, 0($t1)
sw $t3, 0($t0)
sw $t2, 0($t1)
# 移动指针
addi $t0, $t0, 4
addi $t1, $t1, -4
j reverse_loop
end_reverse:
# 此时$a2指向的数组已变为降序,直接调用打印逻辑即可

方式2:双指针从尾部合并(直接生成降序数组)

如果不想依赖升序结果,可以直接用双指针从两个输入数组的末尾开始比较,将较大的元素放入新数组的末尾:

# 假设数组1基地址$a0,长度$s0;数组2基地址$a1,长度$s1
# 降序数组基地址$a2,总长度$s3 = $s0 + $s1
addi $t0, $s0, -1     # 数组1的尾部索引
addi $t1, $s1, -1     # 数组2的尾部索引
addi $t2, $s3, -1     # 降序数组的填充索引(从尾部开始)

merge_desc_loop:
blt $t0, $zero, copy_arr2  # 数组1已遍历完,复制数组2剩余元素
blt $t1, $zero, copy_arr1  # 数组2已遍历完,复制数组1剩余元素

# 计算两个数组当前尾部元素的地址
sll $t3, $t0, 2
add $t3, $t3, $a0
lw $t4, 0($t3)

sll $t5, $t1, 2
add $t5, $t5, $a1
lw $t6, 0($t5)

bgt $t4, $t6, take_arr1  # 数组1元素更大,取它
take_arr2:
sll $t7, $t2, 2
add $t7, $t7, $a2
sw $t6, 0($t7)
addi $t1, $t1, -1
j merge_next
take_arr1:
sll $t7, $t2, 2
add $t7, $t7, $a2
sw $t4, 0($t7)
addi $t0, $t0, -1
merge_next:
addi $t2, $t2, -1
j merge_desc_loop

copy_arr2:
blt $t1, $zero, end_merge_desc
sll $t5, $t1, 2
add $t5, $t5, $a1
lw $t6, 0($t5)
sll $t7, $t2, 2
add $t7, $t7, $a2
sw $t6, 0($t7)
addi $t1, $t1, -1
addi $t2, $t2, -1
j copy_arr2

copy_arr1:
blt $t0, $zero, end_merge_desc
sll $t3, $t0, 2
add $t3, $t3, $a0
lw $t4, 0($t3)
sll $t7, $t2, 2
add $t7, $t7, $a2
sw $t4, 0($t7)
addi $t0, $t0, -1
addi $t2, $t2, -1
j copy_arr1

end_merge_desc:
# 降序数组已生成,调用打印逻辑

三、额外注意事项

  • 确保所有数组的内存空间提前分配足够(总长度*4字节),避免越界写入
  • 打印分隔符时,注意最后一个元素后不要输出多余的逗号,可以在循环内判断是否是最后一个元素再打印分隔符

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:13:40