MIPS汇编字符串比较实现疑问:字符串传递与字符读取问题求助
Hey there! Let's work through your MIPS string comparison problem—you're on the right track with your second approach, just need to fix some syntax and conceptual gaps. First, let's clarify how string labels work in MIPS, then we'll fix your code.
When you define a string in the .data section like this:
.data string1: .asciiz "hello"
The assembler stores the bytes 'h', 'e', 'l', 'l', 'o', '\0' (the null terminator) in consecutive memory locations. The label string1 is just a compile-time alias for the starting memory address of that byte sequence.
Crucially:
- Labels are not variables—you can't reassign what
string1points to at runtime. They're fixed addresses set when you assemble your code. - You can't "assign one labeled string to another" because that would require changing a fixed address, which isn't possible. Instead, you pass the addresses of the strings to your comparison routine.
Your second approach (using $a0 and $a1 to hold string addresses) is correct—you just messed up the addressing syntax and used the wrong instructions for loading immediate values. Here's the corrected, working version:
# Subroutine: compare # Compares two null-terminated ASCII strings # Inputs: # $a0 = Starting address of first string # $a1 = Starting address of second string # $a2 = Address of target label to jump to after comparison # Output: # $s0 = 1 if strings are equal, 0 if not compare: li $s0, 0 # Initialize index counter to 0 (use li, NOT la!) c_for: # Calculate address of current character in string1: base + index add $t0, $a0, $s0 lb $s6, ($t0) # Load byte from string1 at current index # Calculate address of current character in string2 add $t1, $a1, $s0 lb $s7, ($t1) # Load byte from string2 at current index bne $s6, $s7, notequal # Characters don't match → strings are unequal beq $s7, '\0', equal # Hit null terminator → strings are equal addi $s0, $s0, 1 # Increment index for next character j c_for equal: li $s0, 1 # Set result to 1 (equal) j finish notequal: li $s0, 0 # Set result to 0 (not equal) finish: jr $a2 # Jump to the target label stored in $a2
Key Fixes Explained:
- Use
liinstead oflafor immediate values:la $s0, 0tries to load the address of a label named0(which doesn't exist).li $s0, 0loads the numerical value 0 into$s0—exactly what you need for your index counter. - Correct register-offset addressing:
MIPS doesn't support syntax likelb $s6, ($a0)($s0)directly. You have to calculate the full memory address by adding the base string address ($a0/$a1) and index ($s0) into a temporary register, then load from that address. - Check for the null terminator:
Your original code checked for a newline (' '), but null-terminated strings end with'\0'(ASCII 0). This is the correct marker for the end of the string.
Your first idea of "assigning one labeled string to another" comes from a high-level language mindset, but it doesn't translate to assembly:
- Labels are fixed addresses, not mutable variables. You can't redefine what
string1points to at runtime. - If you want to compare pre-defined
.datastrings, just load their addresses into$a0and$a1before calling the subroutine, like this:
.data str1: .asciiz "test" str2: .asciiz "test" post_compare: # Code to run after comparison finishes .text main: la $a0, str1 # Load address of str1 into $a0 la $a1, str2 # Load address of str2 into $a1 la $a2, post_compare # Load address of target label into $a2 jal compare # Call the comparison subroutine
.asciizstrings are stored as byte sequences ending with a null byte (\0).- A string label is just the memory address of the first byte of the string.
- To access a character at index
n, calculate the address asstring_address + n, then load the byte from that address. - Use
lifor loading numerical values,laonly for loading the address of a label.
内容的提问来源于stack exchange,提问作者Werek

