You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS程序触发address out of range错误,请求排查问题原因

问题分析与修复

核心问题

你遇到的地址越界错误,根源在于三个关键问题:

  1. 数组结构定义错误
    你用.asciiz连续定义字符串,这会把所有字符串拼接成一段连续的字节序列,而非存储字符串指针的数组。当你试图通过sll $a2, 2(按4字节指针索引)取元素时,实际取到的是字符串的字节内容,而非目标字符串的地址。

  2. array_size未初始化
    .space 64仅分配64字节空间,未设置初始值,lw $a1, array_size会读取到随机垃圾值,后续逻辑依赖该值会导致不可预测行为。

  3. PrintIntArray逻辑错误
    你用lw $a0, 0($t0)取出的是字符串字节数据,却用li $v0, 4(打印字符串的系统调用)处理,系统会把这个字节数据当成内存地址访问,自然触发地址越界(比如错误中的0x7265746e就是prompt里"retn"的ASCII值)。

修复步骤

1. 修正数组定义

把array改成存储字符串地址的指针数组,用.word保存每个.asciiz字符串的标签:

.data 
    array_size: .word 16  # 明确初始化数组大小为16(0-f共16个元素)
    str0: .asciiz "0x0"
    str1: .asciiz "0x1"
    str2: .asciiz "0x2"
    str3: .asciiz "0x3"
    str4: .asciiz "0x4"
    str5: .asciiz "0x5"
    str6: .asciiz "0x6"
    str7: .asciiz "0x7"
    str8: .asciiz "0x8" 
    str9: .asciiz "0x9" 
    stra: .asciiz "0xa"
    strb: .asciiz "0xb"
    strc: .asciiz "0xc"
    strd: .asciiz "0xd"
    stre: .asciiz "0xe"
    strf: .asciiz "0xf" 
    array:
        .word str0, str1, str2, str3, str4, str5, str6, str7
        .word str8, str9, stra, strb, strc, strd, stre, strf
    prompt: .asciiz "Please enter an integer from 1 to 15: "

2. 调整PrintIntArray逻辑

现在array是指针数组,lw $a0, 0($t0)取出的就是目标字符串的地址,直接用syscall 4打印即可。同时添加范围检查,避免输入超出0-15导致越界:

PrintIntArray:
    addi $sp, $sp, -12
    sw $ra, 0($sp)   
    sw $s0, 4($sp) 
    sw $s1, 8($sp)  
    move $s0, $a0
    move $s1, $a1 

    # 范围检查:输入必须在0到array_size-1之间
    slti $t2, $a2, 0
    bne $t2, $zero, exit_print
    slt $t2, $a2, $s1
    beq $t2, $zero, exit_print

    sll $t1, $a2, 2
    add $t0, $t1, $s0
    lw $a0, 0($t0)

    li $v0, 4
    syscall

exit_print:
    lw $ra, 0($sp)   
    lw $s0, 4($sp) 
    lw $s1, 8($sp)
    addi $sp, $sp, 12

    jr $ra

3. 修正main中的array_size读取

array_size现在用.word存储数值,lw $a1, array_size可以正确读取到16,无需额外修改。

修正后的完整代码

.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 

    # 范围检查:输入必须在0到array_size-1之间
    slti $t2, $a2, 0
    bne $t2, $zero, exit_print
    slt $t2, $a2, $s1
    beq $t2, $zero, exit_print

    sll $t1, $a2, 2
    add $t0, $t1, $s0
    lw $a0, 0($t0)

    li $v0, 4
    syscall

exit_print:
    lw $ra, 0($sp)   
    lw $s0, 4($sp) 
    lw $s1, 8($sp)
    addi $sp, $sp, 12

    jr $ra
    
.data 
    array_size: .word 16
    str0: .asciiz "0x0"
    str1: .asciiz "0x1"
    str2: .asciiz "0x2"
    str3: .asciiz "0x3"
    str4: .asciiz "0x4"
    str5: .asciiz "0x5"
    str6: .asciiz "0x6"
    str7: .asciiz "0x7"
    str8: .asciiz "0x8" 
    str9: .asciiz "0x9" 
    stra: .asciiz "0xa"
    strb: .asciiz "0xb"
    strc: .asciiz "0xc"
    strd: .asciiz "0xd"
    stre: .asciiz "0xe"
    strf: .asciiz "0xf" 
    array:
        .word str0, str1, str2, str3, str4, str5, str6, str7
        .word str8, str9, stra, strb, strc, strd, stre, strf
    prompt: .asciiz "Please enter an integer from 1 to 15: "

内容的提问来源于stack exchange,提问作者Novicecoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:50:30