Home > OS >  Mips address out of range
Mips address out of range

Time:12-12

I'm getting the error: Runtime exception at 0x00400060: address out of range 0x7265746e . The error specifically occurs at the system call on line 35. I am trying to print the second index of the array, but the address is off a bit? No matter what index I try to get the address is pointing to a part of the "prompt" string. Not sure what I am doing wrong

.text 
.globl main 
main: 
    la $a0, array
    lw $a1, array_size
    
    li $v0, 4
    la $a0, prompt
    syscall
    
    li $v0, 5
    syscall
    
    move $a2, $v0
    
    jal PrintIntArray 
     
    li $v0, 10
    syscall

PrintIntArray:
    addi $sp, $sp, -12
    sw $ra, 0($sp)   
        sw $s0, 4($sp) 
        sw $s1, 8($sp)  
        move $s0, $a0
        move $s1, $a1 
        
        sll $t1, $a2, 2
    add $t0, $t1, $s0
    lw $a0, 0($t0)
    
    li $v0, 4
    syscall
    
    lw $ra, 0($sp)   
        lw $s0, 4($sp) 
        lw $s1, 8($sp)
        addi $sp, $sp, 12
    
    jr $ra
    
.data 
    array_size: .space 64
    array: 
        .asciiz "0x0"
        .asciiz "0x1"
        .asciiz "0x2"
        .asciiz "0x3"
        .asciiz "0x4"
        .asciiz "0x5"
        .asciiz "0x6"
        .asciiz "0x7"
        .asciiz "0x8" 
        .asciiz "0x9" 
        .asciiz "0xa"
        .asciiz "0xb"
        .asciiz "0xc"
        .asciiz "0xd"
        .asciiz "0xe"
        .asciiz "0xf" 
       
    prompt: .asciiz "Please enter an integer from 1 to 15: "

CodePudding user response:

We can debug this kind of thing fairly easily.  How?

First, some basic information:

  • syscall #4 takes an address of a string in $a0.

  • Strings are a data structure of varying, potentially long length, so they are stored in memory.  A C-style string uses an ASCII NUL character (value 0x00) to indicate the end of the string (the NUL character takes storage but is not part of the data characters of the string).  We can refer to an entire string by one memory address, namely the lowest address, which is also the address of the first byte of the string.  Other bytes, when present, are at consecutive, increasing addresses.

Next, some tooling:

MARS, RARS, and QtSPIM offer memory configuration, a data view window, and, a label location window.

  • The memory configuration looks like this, and, for global data like your strings, the relevant value is the .data base address.

enter image description here

The others can be accessed immediately after assembly and before running your first line of assembly, i.e. using the debugger feature.

enter image description here

To keep to just one more screen shot, I have executed the first two lines of machine code in this screen capture.

  • One window, called Labels, shows the memory address of the code & data labels.  I have highlighted your array label.

  • Another window, called Data Segment, shows your data using a word-oriented memory dump view.  Ideally for this data, we would have a byte-oriented memory view instead, but we don't, and so, need to interpret the data from the display of words as follows: 0x7265746e, highlighted, is ascii characters from your data, namely, 0x72, 0x65, 0x74, 0x6e, but in reverse due to little endian, so really, 0x6e, 0x74, 0x65, 0x72, which is n, t, e, r, coming from your string "Please enter an integer from 1 to 15: "

  • Also that $a0 reflects the la $a0, array having executed, and we can see that in $a0.

Beyond the data view, there is single step debugging, where it will stop after each line executed and you can manually verify the state of the program and the control flow, which are that the effect of some instruction operated on the proper data (register or memory) and that the proper next instruction is about to be run.  If either of these things aren't true to your expectations, then figure out why and fix.  Sometimes, we don't identify a bug until some inappropriate value is used, and then we have to look earlier in the execution to find why that value was obtained and what earlier part of the program was in error or omission.

You can find all manner of bugs using these features.  For example, as the first syscall #4 to write a prompt repurposes the $a0 register, which had previously been set up by the first line to refer to array, then so, the call to PrintIntArray receives a pointer to the prompt in $a0 rather than to the array.

  • Related