mips - 将 2D 阵列实现为 1D 阵列 (MIPS) 的内存寻址问题
问题描述
我试图将 2D 拼图表示为 1D 数组。目前,我正在尝试使用空单元格测试一个简单的 2x2 拼图。在 MIPS 中,定义如下:
puzzle:
.word 0, 0, 0, 0
对于测试,这应该是我得到的输出:
+---+---+
| | |
但是,这就是我得到的:
+---+---+
| | | |
Error #16: Attempt to use nonexistent memory
Fault address: 004000d0
Register contents:
$zero: 00000000 $at: 00000000 $v0: 00000004 $v1: 00000000
$a0: 00000000 $a1: 00000015 $a2: 00000002 $a3: 00000000
$t0: 00000000 $t1: 00000054 $t2: 00000000 $t3: 00000000
$t4: 00000000 $t5: 00000000 $t6: 00000000 $t7: 00000000
$s0: 00000002 $s1: 00000000 $s2: 00000015 $s3: 10000054
$s4: 00000000 $s5: 00000000 $s6: 00000000 $s7: 00000000
$t8: 00000000 $t9: 00000000 $k0: 00000000 $k1: 00000000
$gp: 00000000 $sp: 7fffeac8 $fp: 00000000 $ra: 00400188
pc: 004000d4 hi: 00000000 lo: 00000000
Current instruction: 8e620000 (at 004000d0)
Decoded instruction: lw $v0, 0($s3) (0x10000054)
我已经花时间单步调试调试器并手动跟踪寄存器,但我对内存中的问题在哪里感到困惑。它列出的指令是当我在 getElement 中读取内存时,但我不确定如何访问我不应该访问的内存。我想知道是否有人注意到 getElement 或 printTop 在访问内存方面有什么问题?
# Name: getElement
#
# Description: Gets the value at the specified coordinates in the puzzle.
#
# Arguments: a0 The x-coordinate
# a1 The y-coordinate
# a2 The size n
#
# Returns: The element at array[n * row + col]
#
getElement:
addi $sp, $sp, -FRAMESIZE_24
sw $ra, 16($sp)
sw $s3, 12($sp)
sw $s2, 8($sp)
sw $s1, 4($sp)
sw $s0, 0($sp)
move $s0, $a2 # store n
move $s1, $a0 # store row
move $s2, $a1 # store col
la $s3, puzzle # get address of array
mul $t0, $s0, $s1 # n * row
add $t1, $t0, $s2 # (n * row) + col
sll $t1, $t1, 2
add $s3, $s3, $t1
lw $v0, 0($s3)
lw $ra, 16($sp)
lw $s3, 12($sp)
lw $s2, 8($sp)
lw $s1, 4($sp)
lw $s0, 0($sp)
addi $sp, $sp, FRAMESIZE_24
jr $ra
# Name: printTop
#
# Description: Prints the top of each "row" for a given cell in a row.
# Ex:
# +---+
# top -> |\##|
# |#\#|
# |##\|
# +---+
#
# Arguments: a0 The array containing the cells in the puzzle
# a1 The size n
# a2 The current row
#
# Returns: Nothing
#
printTop:
addi $sp, $sp, -FRAMESIZE_20
sw $ra, 12($sp)
sw $s2, 8($sp)
sw $s1, 4($sp)
sw $s0, 0($sp)
move $s0, $a0
move $s1, $a1
move $s2, $a2
li $t1, 0 # col = 0
j top_loop
top_loop:
beq $t1, $s1, top_done
move $a0, $s2
move $a1, $t1
move $a2, $s1
jal getElement
# if empty
beq $v0, $zero, t_empty
t_empty:
# print " |"
li $v0, PRINT_STRING
la $a0, empty
syscall
addi $t1, $t1, 1
j top_loop
top_done:
lw $ra, 12($sp)
lw $s2, 8($sp)
lw $s1, 4($sp)
lw $s0, 0($sp)
addi $sp, $sp, FRAMESIZE_20
jr $ra
编辑:我一直在修改一些代码,并且我认为它非常接近工作。在 printTop 继续之前,我将大小 n 减去 1 并更改beq $t1, $s1, top_done
为 bgt $t1, $s1, top_done
,现在我得到的输出是这样的:
+---+---+
| | |
太棒了!除了我也只是直接在 main 中调用 printTop 进行测试,所以当我实际在循环中运行它时,我得到了这个:
+---+---+
| | |
|
|
+---+---+
| |
|
|
+---+---+
因此,由于某种原因,第二行只打印一个单元格,但看起来我不再访问不存在的内存。关于这是什么原因的任何想法?
解决方案
查看寄存器转储:
$s0: 00000002 $s1: 00000000 $s2: 00000015 $s3: 10000054
s2 看起来很可疑,因为它应该是列 - 我期望 0 或 1. a1,它的设置位置是相同的值,并且是从 printTop 中的 t1 设置的
虽然 t1 在 printToo 中为 col 增加看起来不错,但它没有被保存,但寄存器也在 getElement 中使用
因此,问题的一个原因是 t1 由于多种原因被用于多个功能。
推荐阅读
- javascript - 对象删除属性的列表数组
- mysql - MySQL COUNT 的分组行
- reactjs - 在反应中创建动态树
- coq - HoTT 的 Coq:证明 || P-> X || -> (P-> ||X||)
- c# - 在 RazorPage 和 UrlHelper 之间放置一个类似中间件
- c# - 如何在不重新启动实时 Web 应用程序的情况下更改 Oracle 表模式?
- java - Pentaho - 使用 XUL 定义时出错
- inno-setup - 为什么我们在 Inno Setup 的 ExtractTemporaryFiles 函数中指定路径?
- c# - 使用 TcpListener C# 获取客户端的公共 IP 地址
- sql - 如何从 SQL 查询中排除一个特定日期?