2

I'm trying to represent a 2D puzzle as a 1D array. Currently, I'm trying to test having a simple 2x2 puzzle with empty cells. In MIPS, this is defined as the following:

puzzle:
    .word 0, 0, 0, 0

For the test, this should be what I get as output:

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

But, this is what I get:

+---+---+
|   |   |   |
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)

I already spent time stepping through the debugger and keeping track of the registers by hand, but I am stumped as to where the issue in memory is. The instruction it lists is when I read the memory in getElement, but I'm not sure how I could be accessing memory I shouldn't. I was wondering if anyone noticed anything off with getElement or printTop in regards to accessing memory?

# 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

Edit: I've been tinkering around with some of the code and got it very close I think to working. I subtracted the size n by 1 before going on in printTop and changed beq $t1, $s1, top_done to bgt $t1, $s1, top_done and now the output I get is this:

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

Which is great! Except I was also just testing with a call to printTop directly in main, so when I actually run it in a loop I get this:

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

So for some reason for the second row it only prints one cell, but it looks like I'm no longer accessing nonexistent memory. Any ideas as to what the cause of this is?

70ny
  • 33
  • 4

1 Answers1

0

Looking at the register dump:

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

s2 looks suspect as its supposed to be the column - I would expect 0 or 1. a1, where it is set from is same value, and is being set from t1 in printTop

and although t1 looks ok incrementing in printToo for col, it isn't saved but the register is also used in getElement

So the one line cause of the issue is t1 is being used in multiple functions for multiple reasons.

lostbard
  • 5,065
  • 1
  • 15
  • 17
  • I feel so dumb. I changed the code back to what it was before and just substituted the t registers used within getElement for s registers and now it works fine. Thank you so much for the help! For future reference, when should I be using s registers vs t registers? Would it be bad practice to just use all of one over the other? Like I tried to use the t registers for when I did operations, but it clearly led to issues. – 70ny Nov 20 '18 at 18:40
  • See https://stackoverflow.com/questions/20111326/mips-assembly-language-temporary-register-vs-saved-registers for t vs s registers – lostbard Nov 20 '18 at 20:25