MIPS Address out of range (MARS)

37,518

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.

Share:
37,518
Okarin
Author by

Okarin

Updated on October 02, 2020

Comments

  • Okarin
    Okarin over 3 years

    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?

    • Konrad Lindenbach
      Konrad Lindenbach over 10 years
      You only allocated 4 bytes so your string can be at most 3 characters plus a null byte
    • Michael
      Michael over 10 years
      "but i still get the same error". From the looks of it, you only made half of the necessary changes. You're allocating memory that you're reading the strings into, but you're still storing incorrect pointers into array (consider what $v0 will contain when you reach the sw $v0, 0($s2) #save name line).
    • Okarin
      Okarin over 10 years
      I tried making some changes, but all i succeeded in doing was getting new types of errors. What i am trying to do is to save the inputs in a sequence (int, string, int, string etc.) and then just print them. And i have trouble in having them in this sequence, ponting them out and printing them correctly.
  • Okarin
    Okarin over 10 years
    Thanks for the quick answer, i will try to fix it. Thanks for the big help.
  • Michael
    Michael over 5 years
    li $a0,4 and la $a0,4 assemble into exactly the same machine code, so this change would have no effect at all on the problem.