MIPS Address out of range (MARS)

Okarin picture Okarin · Sep 15, 2013 · Viewed 32k times · Source

I'm trying to write a simple code which save string and integer input into an array and then prints them (i will also later add another part which sorts them,but i have to get this to work first).

.data
array:      .space  40  #10 elements array


in_name:
   .asciiz "\nInsert name: "
in_date:
   .asciiz "\nInsert date (mmdd): "
appt:
   .asciiz "\nList: "
spaz:       .asciiz " "

.text
main:       

    la  $s0, array      #load array in s0
    addi    $t0, $zero, 0       #t0=0 counter
    addi    $s1, $zero, 0       #s1=0 array size counter
            j    Input

Input:
        li  $v0, 4           
    la  $a0, in_date
    syscall             #ask date 
    li  $v0, 5          
    syscall             #read date
    add     $t1, $zero, $t0                #offset in t1
    add     $t1, $t1, $t1           #t1*2
    add     $t1, $t1, $t1           #t1*4
    add     $s2, $t1, $s0           #array with offset in s2
    sw  $v0, 0($s2)     #save date
    addi    $t0, $t0, 1     #t0++
    addi    $s1, $s1, 1     #array size counter +1
    li      $v0, 4
    la      $a0, in_name          
    syscall                         #ask name
    li      $v0, 8
    syscall                         #read name
    add     $t1, $zero, $t0                #offset in t1
    add     $t1, $t1, $t1           #t1*2
    add     $t1, $t1, $t1           #t1*4
    add     $s2, $t1, $s0           #array with offset in s2
    sw  $v0, 0($s2)     #save name
    addi    $s1, $s1, 1     #array size counter +1
    addi    $t0, $t0, 1     #t0++
    beq $s1, 10, print          #if array size=10 go to print
    j   Input               #start over until s1=10



   print:
    la  $a0, appt           
    li  $v0, 4          
    syscall             #print list
    addi    $t0, $zero, 0       #t0=0 counter

res:
    add     $t1, $zero, $t0                #offset in t1
    add     $t1, $t1, $t1           #t1*2
    add     $t1, $t1, $t1           #t1*4
    add     $s2, $t1, $s0           #array with offset in s2
    lw  $a0, 0($s2)     #load date
    li  $v0, 1          
    syscall             #print data
    addi    $t0, $t0, 1             #t0++
    la  $a0, spaz               #load space
    li  $v0, 4          
    syscall             #print space
    add     $t1, $zero, $t0                #offset in t1
    add     $t1, $t1, $t1           #t1*2
    add     $t1, $t1, $t1           #t1*4
    add     $s2, $t1, $s0           #array with offset in s2
    lw  $a0, 0($s2)     #load name
    li      $v0, 4
    syscall                         #print name
    addi    $t0, $t0, 1             #t0++
    la      $a0, spaz             
    syscall                         #print space
    addi    $t0, $t0, 1     #t0++ counter
    bne $t0, $s1, res           #start over until t0=s1
    j   end         
 end:
    li  $v0, 10         
    syscall             #the end

With MARS i get this: line 75: Runtime exception at 0x004000e4: address out of range 0x00000008. The code seems to read correctly, and it prints the first integer i input, and then i get an error when it tries to print the first string. I'm new to mips so the code is probably really bad, and i have some trouble dealing with arrays. What am i doing wrong?

Edit: Thanks to Michael answer i understood what i was doing wrong, but it looks like i don't understand how to do it correctly. I tried adding this code

    li      $a0, 4                 
    li      $v0, 9
    syscall                         #space for new word (4bytes)
    move    $a0, $v0
    li      $a1, 4
    li      $v0, 8
    syscall                         #read name

before the read_string but i still get the same error. How should i do it?

Answer

Michael picture Michael · Sep 15, 2013

Syscall 8 (read_string) expects a buffer address in $a0 and a buffer length in $a1. It does not return anything.
So what you're doing here:

li      $v0, 8
syscall             #read name
...
sw  $v0, 0($s2)     #save name

is store the syscall number (8) in your array. And later when you try to print the string, there will be an attempt to print whatever is at address 8, which is why you get the address out of range 0x00000008 error.

You need to allocate some memory for each string. Either statically, in the .data or .bss section, or dynamically using the sbrk syscall. Then for each string, pass the pointer to the correspoing buffer and its length to the read_string syscall, and store the pointer in your array.