首页 > 解决方案 > 将 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_donebgt $t1, $s1, top_done,现在我得到的输出是这样的:

+---+---+
|   |   |

太棒了!除了我也只是直接在 main 中调用 printTop 进行测试,所以当我实际在循环中运行它时,我得到了这个:

+---+---+
|   |   |
|
|
+---+---+
|   |
|
|
+---+---+

因此,由于某种原因,第二行只打印一个单元格,但看起来我不再访问不存在的内存。关于这是什么原因的任何想法?

标签: mipsmemory-address

解决方案


查看寄存器转储:

$s0: 00000002   $s1: 00000000   $s2: 00000015   $s3: 10000054

s2 看起来很可疑,因为它应该是列 - 我期望 0 或 1. a1,它的设置位置是相同的值,并且是从 printTop 中的 t1 设置的

虽然 t1 在 printToo 中为 col 增加看起来不错,但它没有被保存,但寄存器也在 getElement 中使用

因此,问题的一个原因是 t1 由于多种原因被用于多个功能。


推荐阅读