MIPS地址超出范围(MARS)

时间:2013-09-15 08:42:18

标签: assembly mips mars-simulator

我正在尝试编写一个简单的代码,将字符串和整数输入保存到数组中然后打印它们(我稍后还会添加另一个对它们进行排序的部分,但我必须首先使其工作)。

.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

使用MARS我得到:第75行:0x004000e4处的运行时异常:地址超出范围0x00000008。代码似乎正确读取,它打印我输入的第一个整数,然后我尝试打印第一个字符串时出错。我是mips的新手,所以代码可能非常糟糕,我在处理数组时遇到了一些麻烦。我做错了什么?

编辑:感谢迈克尔回答我理解我做错了什么,但看起来我不明白如何正确地做到这一点。我尝试添加此代码

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

但我仍然得到相同的错误。我该怎么办?

2 个答案:

答案 0 :(得分:4)

Syscall 8(read_string)期望$a0中的缓冲区地址和$a1中的缓冲区长度。它没有返回任何东西。
那你在这里做什么:

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

将系统调用号(8)存储在数组中。稍后当您尝试打印字符串时,将尝试打印地址8处的任何内容,这就是您收到address out of range 0x00000008错误的原因。

您需要为每个字符串分配一些内存。静态地,.data.bss部分,或动态使用sbrk系统调用。然后对于每个字符串,将指针传递给相应的缓冲区,并将其长度传递给read_string系统调用,并将指针存储在数组中。

答案 1 :(得分:0)

这是您的代码:

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

解决方案是将第一行替换为la $a0, 4