MIPS程序触发address out of range错误,请求排查问题原因
问题分析与修复
核心问题
你遇到的地址越界错误,根源在于三个关键问题:
数组结构定义错误
你用.asciiz连续定义字符串,这会把所有字符串拼接成一段连续的字节序列,而非存储字符串指针的数组。当你试图通过sll $a2, 2(按4字节指针索引)取元素时,实际取到的是字符串的字节内容,而非目标字符串的地址。array_size未初始化
.space 64仅分配64字节空间,未设置初始值,lw $a1, array_size会读取到随机垃圾值,后续逻辑依赖该值会导致不可预测行为。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
相关产品推荐
相关产品推荐

