0

I am attempting to build an array of integers to represent edges (index of source | index of destination | weight) in an implementation of Dijkstra’s Algorithm using MIPS.

On running with rsim, I am getting an “unaligned word memory reference” error. I think I may be misunderstanding what memory alignment refers to. My .data is below

.data
.align 4

enterNode:          .asciiz "Enter the number of nodes: "
enterEdges:         .asciiz "Enter the number of edges: "
enterSource:        .asciiz "Enter source: "
enterDestination:   .asciiz "Enter destination: "
enterWeight:        .asciiz "Enter weight: "
newLine:            .asciiz "\n"
min_nodes:          .word 1
max_nodes:          .word 20
error1:             .asciiz "Invalid number of nodes. Must be between 1 and 20.\n"
error2:             .asciiz "Invalid number of edges. Must be between 0 and 400.\n"
edgeArr:            .space 4800
    # source | destination | weight
input:              .space 5

In the .text, I am looping for the number of edges to input the data into the array, but it seems the way I am referring to or calculating the address is incorrect.

addi    $t0, $zero, 0                   # Edge counter
la      $t1, edgeArr
addi    $t2, $zero, 0

loop:
    # Source
    addi    $v0, $zero, PRINT_STRING    # Print user prompt
    la      $a0, enterSource
    syscall
    addi    $v0, $zero, READ_INT        # Take user input
    syscall
    add     $t3, $t2, $t2               # Calculate address in array
    add     $t3, $t3, $t3
    add     $t3, $t1, $t3
    sw      $v0, ($t3)
    addi    $t2, $t2, 1

    # ...destination and weight are effectively identical to source...

    # Loop condition
    addi    $t0, $t0, 1
    slt     $t4, $t0, $s1
    bne     $t4, $zero, loop

I’ve looked at several similar questions but they don’t seem to quite address the portion I’m misunderstanding, and I could really benefit from a fresh pair of eyes looking at this.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Gladdstone
  • 72
  • 7

1 Answers1

3

You have some strings between the .align 4 and your .space directive. (.word implicitly aligns by 4 in classic MIPS assemblers like MARS, but .space doesn't.)

.align 4 pads to make the current position a multiple of 2^4 = 16. (You probably want .align 2 to get 1<<2 = 4 byte alignment). The total size of the strings are not a multiple of 4, so your .space directives are not at word-aligned memory addresses.

Fix this by putting the word-aligned objects first, then the odd-length data.

.data
.align 4
min_nodes:          .word 1
max_nodes:          .word 20

edgeArr:            .space 4800
    # source | destination | weight
input:              .space 5              # 5 bytes??


enterNode:          .asciiz "Enter the number of nodes: "
enterEdges:         .asciiz "Enter the number of edges: "
enterSource:        .asciiz "Enter source: "
enterDestination:   .asciiz "Enter destination: "
enterWeight:        .asciiz "Enter weight: "
newLine:            .asciiz "\n"
error1:             .asciiz "Invalid number of nodes. Must be between 1 and 20.\n"
error2:             .asciiz "Invalid number of edges. Must be between 0 and 400.\n"

If min_nodes is a build-time constant, define it with .equ instead of storing it in memory at all. (So you can use it as an immediate constant)

.equ  min_nodes, 1
.equ  max_nodes, 20

...
li   $t0, min_modes

Or sltiu $t1, $t0, min_modes to set $t1=1 if $t0 < min_nodes (unsigned), otherwise set it to zero. And BTW, you can do a range check with only one branch:

addui  $t1, $t0, -1
then compare against 19 (unsigned)

Values less than 1 will wrap to a large unsigned value (and compare greater than 19). Values greater than 20 will still be greater than 19.


You also don't need to mix your string constants with read-write values. If your assembler supports a .rodata or .section .rodata, your read-only strings go in the text segment of your executable so they're write-protected.

IIRC, MARS doesn't.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    Thank you, this is exactly the explanation I was looking for. I hadn’t thought about where I was declaring the arrays. I’ll also make sure to change the min and max nodes. You’re correct in that they are simply constants and that would probably be a better way of declaring them. I’m not sure if the assembler supports .rodata but I will look into the documentation. Thank you! – Gladdstone Nov 25 '17 at 03:49