MIPS程序运行时地址异常问题求助
Hey there, let's break down why you're hitting that "Bad address" exception and fix it step by step:
Core Issue: Insufficient Stack Allocation
The biggest problem is in your loop_over_strings function—you only allocate 4 bytes of stack space with addi $sp, $sp, -4, but then try to store three different registers ($ra at 0($sp), $a0 at 4($sp), $a1 at 8($sp)). Accessing 4($sp) and 8($sp) is out of bounds for the 4-byte stack you reserved, which corrupts the stack structure and leads to invalid memory accesses when you try to load values back later.
Other Problems to Fix
- Invalid String Syntax: Your
.asciizline uses HTML-escaped quotes (") instead of regular double quotes ("). QtSpim won't parse this correctly, so your string address will be wrong. - Missing
asciiFunction: You're jumping toasciiwithjalr $a1, but there's no implementation for this function in your code. Without it, the jump will land at an invalid address and trigger another exception. - Redundant
.textSection: You have two.textdeclarations, which is unnecessary and can cause confusion for the assembler.
Fixed Code
Here's the corrected version that should run without exceptions in QtSpim:
.data STR_str: .asciiz "Cow, Bird, Beer" # Fixed quote syntax .text # String traversal function with proper stack handling .globl loop_over_strings loop_over_strings: addi $sp, $sp, -12 # Allocate 12 bytes for 3 registers ($ra, $a0, $a1) sw $ra, 0($sp) sw $a1, 8($sp) # Now safely within allocated stack space loop: sw $a0, 4($sp) lb $t0, 0($a0) # Load current character beqz $t0, end_loop # Exit if we hit the null terminator jalr $a1 # Call the ascii function lw $a0, 4($sp) # Restore $a0 lw $a1, 8($sp) # Restore $a1 addi $a0, $a0, 1 # Move to next character j loop end_loop: lw $ra, 0($sp) # Restore return address addi $sp, $sp, 12 # Deallocate stack space jr $ra # Main function .globl main main: addi $sp, $sp, -4 sw $ra, 0($sp) la $a0, STR_str # Load string address into $a0 la $a1, ascii # Load ascii function address into $a1 jal loop_over_strings lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra # Example implementation of the ascii function # This prints each character from the string ascii: li $v0, 11 # Syscall code for printing a character move $a0, $t0 # Pass the current character to the syscall syscall jr $ra
Key Takeaways
- Always calculate exactly how much stack space you need: each register takes 4 bytes, so multiply the number of registers you're saving by 4.
- Match stack allocation and deallocation: if you subtract 12 from
$spat the start, add 12 back before returning. - Make sure all functions you reference (like
ascii) are implemented—undefined functions lead to invalid jumps.
You can use QtSpim's step-through debugging to watch the $sp register and confirm that all stack accesses are within the allocated space now.
内容的提问来源于stack exchange,提问作者John Smith

