assembly Mips地址超出范围

nimxete2  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(158)

我收到错误:0x00400060处出现运行时异常:地址超出范围0x7265746e。错误具体发生在第35行的系统调用处。我试图打印数组的第二个索引,但地址有点偏离?无论我尝试获取哪个索引,地址都指向“prompt”字符串的一部分。不确定我做错了什么

.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: "
7uzetpgm

7uzetpgm1#

我们可以很容易地调试这种东西。怎么做?
一、一些基本信息:

  • syscall #4获取$a0中字符串的地址。
  • 字符串是一种可变的数据结构,长度可能很长,因此它们存储在内存中。C样式字符串使用ASCII NUL字符(值0x 00)表示字符串的结尾(NUL字符占用存储空间,但不是字符串数据字符的一部分)。我们可以通过一个存储器地址(即最低地址)来引用整个字符串,其也是字符串的第一个字节的地址。当存在其它字节时,它们位于连续的递增地址。

接下来,一些明面上的:
MARS、RARS和QtSPIM提供内存配置、数据视图窗口和标签位置窗口。

  • 内存配置如下所示,对于像字符串这样的全局数据,相关值是.data基址。

在汇编之后和运行第一行汇编之前,可以立即访问其他文件,即使用调试器功能。

为了只保留一个屏幕截图,我已经执行了此屏幕截图中的前两行机器代码。

  • 一个窗口,称为标签,显示内存地址的代码和数据标签。我已经突出显示您的array标签。
  • 另一个窗口叫做Data Segment,它使用面向字的内存转储视图显示数据。理想情况下,我们应该使用面向字节的内存视图来显示这些数据,但是我们没有这样做,因此,我们需要按照如下方式从字的显示中解释数据:突出显示的0x 7265746 e是数据中的ascii字符,即0x 72、0x 65、0x 74、0x 6 e,但由于小字节序,它们是相反的,因此实际上,0x 6 e、0x 74、0x 65、0x 72,即nter,“请输入***n***1到15之间的整数:“
  • 同样,$a0反映了已经执行的la $a0, array,我们可以在$a0中看到。

在数据视图之外,还有单步调试,它将在每执行一行后停止,您可以手动验证程序和控制流的状态,这是一些指令在正确数据上操作的效果(寄存器或内存),并且即将运行正确的下一条指令。如果这些情况中的任何一个不符合您的预期,然后找出原因并修复。有时候,直到使用了不合适的值,我们才发现bug,然后我们必须在执行的早期查找为什么获得了该值,以及程序的哪个早期部分出错或遗漏了。
使用这些特性可以发现各种各样的错误。例如,第一个写prompt的syscall#4重新使用了$a0寄存器,该寄存器先前由第一行设置为引用array,那么,对PrintIntArray的调用接收指向$a0中的prompt的指针,而不是指向array的指针。

相关问题