MIPS 地址超出范围 (MARS)

1 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
Run Code Online (Sandbox Code Playgroud)

使用 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
Run Code Online (Sandbox Code Playgroud)

在 read_string 之前,但我仍然遇到相同的错误。我该怎么做?

Mic*_*ael 6

系统调用 8( read_string) 需要一个缓冲区地址 in$a0和一个缓冲区长度 in $a1。它不返回任何东西。
所以你在这里做什么:

li      $v0, 8
syscall             #read name
...
sw  $v0, 0($s2)     #save name
Run Code Online (Sandbox Code Playgroud)

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

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