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

MIPS汇编用heap取两数组对应元素最大值时l.d指令报地址越界错误

问题根因与修复方案

你遇到的地址越界异常核心原因是Arr1的基地址被意外覆盖,同时存在多处逻辑错误,具体问题和修复方法如下:

触发异常的直接原因

  • main函数初始阶段你将Arr1的地址存在了$a0寄存器,但后续执行堆分配(syscall 9)时,执行了li $a0, 64,直接把$a0里的Arr1基地址覆盖为立即数64。进入MaxArray函数后,你尝试从$a0指向的地址加载双精度数,此时$a0的值是0x40(十进制64),循环每次地址加8,第三次访问就会到0x50,这类低地址属于系统保护区域,用户程序没有访问权限,直接触发地址越界异常。

其他需要修复的逻辑错误

  1. 计算Arr2的元素数量时写错存储目标:sw $t3, Arr1Count 应该改为 sw $t3, Arr2Count,否则会直接覆盖Arr1的计数。
  2. 浮点数比较用错指令:c.eq.s是单精度浮点数比较指令,双精度需要改为c.lt.d(判断$f0小于$f2的场景),原来的相等判断逻辑也不符合取最大值的需求,正确逻辑是:如果$f0小于$f2就存$f2,否则存$f0。
  3. 堆分配返回地址没有备份:你直接用存储堆首地址的$v0做偏移写入,循环结束后$v0已经指向堆数组末尾,后续打印拿到的是末尾地址,无法正确读取元素,需要在分配完堆之后先把首地址备份到其他寄存器。
  4. 打印函数计数器逻辑错误:PrintLoop里每次累加的是$t0而非循环计数器$t5,会触发死循环,永远无法满足退出条件。
  5. 打印逻辑缺少syscall触发:你设置了$v0=3和$f12的值后没有执行syscall,不会输出任何内容。

修正后的核心代码片段

main函数堆分配部分

# 分配堆内存
li $v0, ALLOC_MEM
li $a0, 64
syscall
move $s0, $v0 # 备份堆首地址,后续传给打印函数
li $t0, 0 # 循环计数器

# 重新给$a0、$a1赋值为两个数组的基地址
la $a0, Arr1
la $a1, Arr2
lw $t1, Arr1Count # 加载数组长度

jal MaxArray

move $a2, $s0 # 传堆首地址给打印函数
move $a3, $t0 # 传元素数量给打印函数

MaxArray比较逻辑部分

Loop: 
    beq $t0,$t1,Continue
    l.d $f0, ($a0) # 从Arr1加载双精度数
    l.d $f2, ($a1) # 从Arr2加载双精度数
    c.lt.d $f0, $f2 # 判断f0 < f2是否成立
    bc1t store_f2 # 条件成立则存储f2
    s.d $f0, ($v0) # 否则存储f0
    j increase
store_f2:   
    s.d $f2, ($v0)
increase:
    addi $a0, $a0, 8
    addi $a1, $a1, 8
    addi $v0, $v0, 8
    addi $t0, $t0, 1
    b Loop
Continue:
    jr $ra

PrintArray打印逻辑部分

PrintArray:
    li $t5, 0 # 打印循环计数器
PrintLoop:
    bge $t5, $a3, exit
    l.d $f2, 0($a2)
    addi $a2, $a2, 8
    # 打印双精度数
    li $v0, 3
    mov.d $f12, $f2
    syscall # 触发打印系统调用
    addi $t5, $t5, 1 # 累加打印循环计数器
    j PrintLoop
exit:
    li $v0, 10
    syscall

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:15:06