为何用于计算数组偶数和的SPIM/MIPS程序无法正常运行?
解决MIPS数组偶数和计算的错误问题
嘿,作为MIPS新手能写出这样的代码已经很出色啦!咱们一步步拆解你遇到的问题,修复代码并理清结果差异~
首先分析报错原因
你遇到的Bad address和执行异常,核心问题是循环终止条件完全错误:
- 你把
$19设为固定值32,然后和存储数组地址的$16做比较。但$16是内存地址(比如初始是0x10000004,每次加4后会变成0x10000008、0x1000000C...),而$19是数值32,两者根本不是同一类型的变量,循环永远不会正常退出,最终导致程序访问了数组之外的非法内存地址,触发错误。
然后看结果错误的原因
你得到的-56其实是当前代码逻辑下的“意外正确”累加结果,但代码还有个关键漏洞:
$10寄存器在累加前没有初始化,它的初始值是随机的垃圾数据,这会导致累加结果不可预测(这次碰巧得到了逻辑上的偶数和,但换个运行环境结果可能完全不同)。
修正后的代码
.text .globl main main: lui $16, 0x1000 # 加载.data段基地址的高16位 lw $17, 0($16) # 读取数组大小size(值为8) addiu $18, $0, 2 # 除数2,用于判断偶数 addiu $19, $0, 0 # 初始化计数器为0 addiu $10, $0, 0 # 初始化累加寄存器$10为0!非常重要 addiu $16, $16, 4 # $16指向数组array的起始地址 loop: beq $19, $17, exit # 计数器等于数组大小时退出循环 lw $20, 0($16) # 读取当前数组元素到$20 div $20, $18 # 元素除以2 mfhi $13 # 获取余数到$13 bne $13, $0, skip # 余数不为0(奇数),跳过累加 add $10, $10, $20 # 是偶数,累加到$10 skip: addiu $16, $16, 4 # 地址移动到下一个元素 addiu $19, $19, 1 # 计数器加1 j loop # 回到循环开头 exit: sll $0, $0, 0 # 空指令,占位用 .data size: .word 8 array: .word 23, -12, 45, -32, 52, -72, 8, 13
代码修正点说明
- 初始化累加寄存器:在开头添加
addiu $10, $0, 0,确保$10从0开始累加,避免垃圾数据干扰结果。 - 正确的循环终止条件:用计数器
$19和数组大小$17(值为8)比较,循环8次后退出,彻底避免访问非法内存。 - 优化分支逻辑:把奇数的处理改成
bne ... skip,减少分支跳转的复杂度,让代码逻辑更清晰。 - 独立寄存器存数组元素:用
$20存当前读取的数组元素,避免覆盖用来存储数组大小的$17。
关于结果的说明
按照你给出的数组,偶数元素是-12、-32、52、-72、8,它们的和是:-12 + (-32) + 52 + (-72) + 8 = -56
所以修正后的代码运行后,$10的值会是-56,这是数学上的正确结果。你预期的25可能是计算时混淆了奇数/偶数,或者误将负数当成正数累加了~
内容的提问来源于stack exchange,提问作者Diogenes InAnUrn
相关产品推荐
相关产品推荐

