MIPS环境下打印8x8二维棋盘数组问题求助
MIPS战舰棋盘程序调试问题解决
问题概述
正在开发一款类似战舰的游戏程序,使用8x8二维数组作为棋盘,初始时棋盘中心(第4行对应位置)有一个标记为V的舰船。调试时发现代码仅执行一次内层循环后就跳过,只打印大量换行;尝试在外部循环开始时重置寄存器$t3为0后情况更糟,要么无有效输出,要么仅输出换行。
期望输出格式:
ABCDEFG 1 2 3 4 V 5 6 7
问题代码
.data board: .ascii " ABCDEFG" .ascii "1 " .ascii "2 " .ascii "3 " .ascii "4 V " .ascii "5 " .ascii "6 " .ascii "7 " .text main: #Build the board li $t0, 8 li $t1, 8 la $t6, board li $t2, 0 # set i to 0 for outerloop li $t3, 0 #set j = 0 jal, boardOuterLoop #jump to building board loops boardOuterLoop: bge $t1, $t2, endOuterLoop # basically...for (int i = 0; i < row; i++) li $t3, 0 #reset j = 0 for next ineration through innerloop boardInnerLoop: bge $t3, $t0, endInnerLoop # basically...for(int j = 0; j<col; j++) #find address of each index mul $t4, $t2, $t1 # col* i add $t4, $t4, $t3 # (col* i) + j sll $t4, $t4, 2 # 2^2 * (width * i + j) add $t4, $t6, $t4 #bass add + $t4 addi $t3, $t3, 1 # j++ #print index li $v0, 11 sw $a0, 0($t4) syscall b boardInnerLoop #branch back to beginning of inner loop endInnerLoop: li $v0, 4 la $a0, newline syscall addi $t2, $t2, 1 #i++ b boardOuterLoop endOuterLoop: jr $ra
错误点分析与修复方案
1. 外层循环分支条件颠倒
原外层循环判断bge $t1, $t2, endOuterLoop逻辑完全错误:要实现for(i=0; i<row; i++),应该是当i >= row时才跳转到结束,正确写法是bge $t2, $t1, endOuterLoop,否则会直接跳过整个外层循环。
2. 地址计算冗余且错误
board是用.ascii定义的单字节字符数组,每个元素占1字节,但代码里用了sll $t4, $t4, 2(乘以4),导致地址偏移过大,读取到无效内存数据。直接删除这行即可。
3. 打印逻辑完全搞反
使用syscall 11(打印单个字符)时,需要把目标字符加载到$a0,但原代码用sw $a0, 0($t4)把$a0的值存到内存,完全反向。应该改成lb $a0, 0($t4),从内存读取字符到$a0后再调用打印。
4. 缺失换行符定义
代码里调用la $a0, newline但未在.data段定义该标签,需要添加newline: .asciiz "\n",否则会访问无效地址。
5. 跳转指令语法错误
jal, boardOuterLoop中的逗号是多余的,MIPS指令里jal后直接跟标签,正确写法是jal boardOuterLoop。
修复后的完整代码
.data board: .ascii " ABCDEFG" .ascii "1 " .ascii "2 " .ascii "3 " .ascii "4 V " .ascii "5 " .ascii "6 " .ascii "7 " newline: .asciiz "\n" .text main: # 初始化参数 li $t0, 8 # 列数 li $t1, 8 # 行数 la $t6, board # 棋盘基地址 li $t2, 0 # 外层循环变量i=0 jal boardOuterLoop # 跳转到外层循环 boardOuterLoop: bge $t2, $t1, endOuterLoop # 当i >= 8时结束外层循环 li $t3, 0 # 重置内层循环变量j=0 boardInnerLoop: bge $t3, $t0, endInnerLoop # 当j >=8时结束内层循环 # 计算当前字符地址 mul $t4, $t2, $t1 # i * 列数 add $t4, $t4, $t3 # i*col + j add $t4, $t6, $t4 # 基地址 + 偏移量 # 打印单个字符 li $v0, 11 lb $a0, 0($t4) # 从内存读取字符到$a0 syscall addi $t3, $t3, 1 # j++ b boardInnerLoop # 回到内层循环开头 endInnerLoop: # 打印换行 li $v0, 4 la $a0, newline syscall addi $t2, $t2, 1 # i++ b boardOuterLoop # 回到外层循环开头 endOuterLoop: jr $ra
内容的提问来源于stack exchange,提问作者Sara Malos
相关产品推荐
相关产品推荐

