MIPS汇编栈段扩展失败报错处理及归并排序代码解析
MIPS归并排序栈溢出问题排查与代码解析
一、栈溢出报错的核心原因
你遇到的“无法将栈段扩展16字节至524288字节”报错,本质是栈内存越界写入导致的栈结构破坏,具体问题出在merge函数的栈操作上:
merge: # params: list, l=$t2, m=$t4, r=$t5 add $sp, $sp, -12 # 仅分配12字节栈空间 sw $ra, 0($sp) sw $s1, 4($sp) sw $t2, 8($sp) sw $t1, 12($sp) # 越界!12字节栈的有效索引范围是0-11
你只给栈分配了12字节,但最后一条sw指令试图写入栈的第13个字节(从0开始计数),每次调用merge都会破坏栈外的内存区域,反复操作后最终触发栈溢出报错。
快速修复方案
- 把栈分配大小改成16字节:将
add $sp, $sp, -12改为add $sp, $sp, -16,足够容纳4个寄存器的存储需求 - 修正寄存器恢复顺序(当前出栈顺序和入栈顺序不匹配):
# 错误的恢复顺序 lw $ra, 0($sp) lw $s1, 8($sp) lw $t2, 4($sp) lw $t1, 12($sp) # 改成正确的对应顺序 lw $ra, 0($sp) lw $s1, 4($sp) lw $t2, 8($sp) lw $t1, 12($sp)
二、代码逻辑全解析
1. 主函数(main)流程
- 提示用户输入数组长度
n,循环读取n个元素存入list数组 - 计算数组总字节数(
arraySize)和数组末尾地址(arrayEndAddress) - 调用
mergeSort执行排序,完成后调用printArray输出结果,最后终止程序
2. 迭代式归并排序(mergeSort)
这是迭代版的归并排序(非递归实现),核心逻辑:
- 用
curr_size($t1)表示当前待合并的子数组长度,初始为1,每次循环翻倍 - 外层
for1循环控制子数组长度,直到curr_size超过数组最大索引(n-1) - 内层
for2循环遍历数组,每次选取两个相邻子数组:左子数组范围[left_start, mid],右子数组范围[mid+1, right_end] - 调用
merge合并两个子数组,然后移动到下一组待合并的子数组
3. 合并函数(merge)
负责将两个有序子数组合并回原数组,逻辑框架:
- 把左子数组(
l到m)复制到临时数组Left,右子数组(m+1到r)复制到临时数组Right - 用双指针法遍历
Left和Right,将较小的元素依次写回原数组list - 最后将
Left或Right中剩余的元素全部写回原数组
⚠️ 注意:merge里的RightInput段还有逻辑错误,当前的$t7计算会导致Right数组写入位置混乱,应该改成:
# 错误的写法 add $t7,$t7, $s1 sll $t7, $t7, 2 # 改成正确的索引计算 sll $t7, $s1, 2 # 用s1作为索引,乘以4得到字节偏移
内容的提问来源于stack exchange,提问作者Waldo
相关产品推荐
相关产品推荐

