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

MIPS汇编实现快速排序时栈内存被partition覆盖致数组异常求助

MIPS快速排序递归问题:数组被覆盖的解决思路

看起来你在实现MIPS版快速排序的qsort递归函数时,踩了栈帧管理的典型大坑——这种问题在手写汇编递归时太容易犯了!你的swap已经验证正常,partition是给定的可靠代码,问题完全出在qsort的递归栈管理和参数处理上,下面给你详细分析和修正方案:

核心问题定位

你的自定义RetAddrMng栈管理逻辑完全不符合MIPS的调用规范,这是导致数组被覆盖的根本原因:

  • 栈生长方向搞反了:MIPS的栈是向下生长的(栈指针$sp必须递减来分配新空间),但你用add $sp, $sp, $t6让栈指针向上移动,会直接覆盖栈上方的内存区域(包括递归时需要保存的参数、返回地址,甚至可能干扰到数据段的数组)
  • 临时寄存器滥用:你用$t6作为递归计数,但$t0-$t9是MIPS的临时寄存器,调用其他函数(比如partition)时会被随意覆盖,导致栈偏移计算彻底混乱,返回地址保存的位置完全错误

正确的递归栈帧实现方案

MIPS递归函数的标准写法必须遵循调用约定,下面是qsort的正确实现框架,完全适配你的现有代码:

qsort:
    # 1. 分配栈空间,保存需要保留的寄存器
    # 我们需要保存$ra(返回地址)、$s0(数组指针v)、$s1(n)、$s2(partition返回的p)
    addiu $sp, $sp, -16  # 4个寄存器×4字节=16字节栈空间
    sw $ra, 12($sp)      # 保存返回地址到栈
    sw $s0, 8($sp)       # 保存原数组指针$a0到$s0(调用者保存寄存器,必须保留)
    sw $s1, 4($sp)       # 保存原n值$a1到$s1
    sw $s2, 0($sp)       # 预留位置存partition返回的p

    # 2. 递归终止条件:n <=1 直接返回
    ble $a1, 1, qsort_exit

    # 3. 调用partition函数,获取p值
    move $a0, $s0        # 传入数组指针v
    move $a1, $s1        # 传入n
    jal partition
    move $s2, $v0        # 把partition返回的p保存到$s2(避免被后续调用覆盖)

    # 4. 第一个递归调用:qsort(v, p)
    move $a0, $s0        # 参数1:原数组v
    move $a1, $s2        # 参数2:p
    jal qsort

    # 5. 第二个递归调用:qsort(&v[p+1], n-p-1)
    sll $t0, $s2, 2       # 计算p×4(字节偏移量)
    add $a0, $s0, $t0     # 得到v[p]的地址
    addiu $a0, $a0, 4     # 偏移4字节,得到&v[p+1]
    sub $a1, $s1, $s2     # 计算n-p
    addiu $a1, $a1, -1    # 计算n-p-1
    jal qsort

qsort_exit:
    # 6. 恢复寄存器,释放栈空间
    lw $s2, 0($sp)
    lw $s1, 4($sp)
    lw $s0, 8($sp)
    lw $ra, 12($sp)
    addiu $sp, $sp, 16    # 栈指针恢复到进入函数前的位置
    jr $ra                # 返回调用者

关键规则说明(必须牢记)

  • 寄存器分类:$s0-$s7是调用者保存寄存器,如果你的函数要使用这些寄存器,必须先保存到栈里,退出时恢复;$t0-$t9是临时寄存器,调用其他函数后值会被清空,不能用来保存需要跨函数调用的数据
  • 栈操作规范:分配栈空间必须用addiu $sp, $sp, -size(向下生长),释放时用addiu $sp, $sp, size,绝对不能反向操作
  • 递归参数传递:每次递归调用前,必须重新设置$a0和$a1为当前递归的参数,不能依赖之前的寄存器值——因为之前的函数调用会修改这些参数寄存器

测试建议

  1. 先注释掉两个递归调用,只测试partition的调用逻辑,确认partition返回的p正确且数组没有被破坏
  2. 逐步添加第一个递归调用,验证数组前半部分排序正常
  3. 最后添加第二个递归调用,验证完整排序功能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:06