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

MIPS汇编实现递归求树高报错:地址未按字边界对齐求助

搞定MARS里的“store address not aligned on word boundary”错误

嘿,我一眼就看出你遇到的问题根源了——MIPS是严格要求字操作(4字节的lw/sw)必须用4字节对齐的地址(也就是地址得是4的倍数),而你的代码里生成了0x7这种非对齐地址,直接触发了运行时异常。咱们一步步分析问题,再给你修正后的代码:

问题1:主函数传错了参数给height

看你main里的这段代码:

la $v0, a       # $v0 拿到的是节点a的内存地址(比如0x10010000)
lw $a0, 0($v0)  # 这里居然把a节点里的第一个数值(3)加载到$a0了!
jal height

你把节点的数值传给了height函数,而不是节点的内存地址!这就导致后面height里执行sw $a0, 4($a0)时,算出的地址是4+3=7(0x7),完全不满足4字节对齐要求,直接炸了。

问题2:height函数的递归逻辑完全走偏了

你的height函数现在根本没正确实现递归求高度的逻辑:

  • 没加载左/右子节点的地址去递归调用
  • 没保存两次递归的返回值(h1和h2)
  • 完全没写取最大值加1的计算步骤

修正后的完整代码

我把所有问题都改好了,关键修改处都标出来了:

.data
tree:   .word a
a:      .word 3, y, c    # 每个节点结构:[数据, 左子节点地址, 右子节点地址]
y:      .word 21, d, e
c:      .word 4, 0, 0
d:      .word 5, f, g
e:      .word -3, 0, h
f:      .word 6, 0, 0
g:      .word 9, i, 0
h:      .word 18, 0, w
i:      .word 22, 0, 0
w:      .word 1, 0, 0
answer: .word 0

.text
.globl main
main:
    la $a0, a           # 直接把节点a的地址传给$a0(修改点1:不再加载数值)
    jal height
    sw $v0, answer

    # 打印结果
    li $v0, 1
    lw $a0, answer
    syscall

    # 退出程序
    li $v0, 10
    syscall

#________________________________________
# height函数:输入$a0为节点地址,返回$v0为树的高度
.globl height
height:
    addi $sp, $sp, -16  # 扩容栈空间,要存ra、s0、h1、h2(修改点2)
    sw $ra, 0($sp)
    sw $s0, 4($sp)
    sw $s1, 8($sp)      # s1存左子树高度h1
    sw $s2, 12($sp)     # s2存右子树高度h2

    # 基准情况:空节点(地址为0),返回高度0
    li $v0, 0
    beq $a0, $zero, height_exit

    move $s0, $a0       # 把当前节点地址存到s0,方便后续访问子节点

    # 递归算左子树高度
    lw $a0, 4($s0)      # 加载当前节点的左子节点地址(偏移4字节)(修改点3)
    jal height
    move $s1, $v0       # 把左子树高度存到s1

    # 递归算右子树高度
    lw $a0, 8($s0)      # 加载当前节点的右子节点地址(偏移8字节)(修改点4)
    jal height
    move $s2, $v0       # 把右子树高度存到s2

    # 计算max(h1, h2) + 1
    bge $s1, $s2, use_left_height
    move $v0, $s2
    j add_one_to_height
use_left_height:
    move $v0, $s1
add_one_to_height:
    addi $v0, $v0, 1    # 高度加1,因为当前节点要算一层

height_exit:
    # 恢复栈里的寄存器,回收栈空间
    lw $ra, 0($sp)
    lw $s0, 4($sp)
    lw $s1, 8($sp)
    lw $s2, 12($sp)
    addi $sp, $sp, 16
    jr $ra

关键修改点说明

  1. 参数传递修正:直接用la $a0, a把节点的内存地址传给height,再也不用加载节点里的数值了。
  2. 栈空间调整:因为要保存两次递归的返回值,所以把栈空间从12字节扩到16字节,用来存s1和s2。
  3. 递归逻辑修复:从当前节点的4字节偏移处拿左子节点地址,8字节偏移处拿右子节点地址,分别递归调用height,把返回的高度存起来。
  4. 实现max计算:用bge指令判断哪个子树更高,取最大值后加1,得到当前树的高度。

现在运行这段修正后的代码,应该就能正确算出树的高度,再也不会触发地址对齐的错误啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:02:43