MIPS升序冒泡排序改降序后出现异常输出,求原因解释
bgt cause an abnormal value in my MIPS bubble sort? Problem Description
As a MIPS beginner, I have a working ascending bubble sort code:
.data nums: .word 10 elems: .word 23, 42, 54, 10, 56, 78, 15, 43, 21, 87 space: .asciiz " " end: .asciiz "The end." .text la $s0, elems lw $t4, nums reset: li $t0, 0 #offset li $t5, 0 #count up to nums loop: add $s1, $s0, $t0 lw $s3, ($s1) addi $t1, $t0, 4 add $s2, $s0, $t1 lw $s4, ($s2) bgt $s3, $s4, swap next: addi $t5, $t5, 1 addi $t0, $t0, 4 beqz $t4, exit beq $t5, $t4, nummin j loop nummin: subi $t4, $t4, 1 j reset swap: sw $s3, ($s2) sw $s4, ($s1) j next exit: li $t0, 0 li $t1, 0 loop2: li $v0, 1 add $t2, $s0, $t1 lw $a0, ($t2) syscall li $v0, 4 la $a0, space syscall addi $t0, $t0, 1 addi $t1, $t1, 4 beq $t0, 10, done j loop2 done: li $v0, 4 la $a0, end syscall
It outputs the correct ascending result:
10 15 21 23 42 43 54 56 78 87 The end.
But when I reverse the operands in the bgt instruction to bgt $s4, $s3, swap to implement descending sort, I get this abnormal output:
1750335520 87 78 56 54 43 42 23 21 15
Root Cause Analysis
Your original ascending sort code has a hidden out-of-bounds memory access bug that only surfaces when switching to descending order. Here's the breakdown:
Incorrect comparison count in bubble sort
For an array ofnelements, a single bubble sort pass only needsn-1adjacent comparisons (to avoid accessing beyond the last element). However, your code initializes$t4tonums(10, the total element count) and runs$t4comparisons per pass. This means the first pass tries to compare the 10th element (index 9) with a non-existent 11th element (index 10), which points to memory right after yourelemsarray—the start of thespacestring.Why ascending sort worked without issues
Thespacestring is stored as.asciiz " ", which in memory holds the ASCII space value (0x20) followed by a null terminator (0x00). When loaded as a 4-byte word vialw, this becomes0x20000000(decimal 1750335520). In your ascending logic (bgt $s3, $s4, swap), you only swap if the current element is larger than the next. Since the lastelemselement is 87 (far smaller than0x20000000), the swap condition never triggers. The out-of-bounds access doesn't modify your array, so the output stays correct.Why descending sort causes the abnormal value
When you reverse the operands tobgt $s4, $s3, swap, you now swap if the next element is larger than the current. The out-of-bounds value0x20000000is way larger than 87, so the swap condition fires:- The invalid value
0x20000000gets written into the last position ofelems(index 9). - The value 87 overwrites the
spacestring's memory, corrupting your separator. - In subsequent bubble sort passes, this extremely large value will be swapped to the front of the array (since descending order prioritizes larger elements first), making it the first printed value.
- The corrupted
spacestring may cause unexpected formatting, though in your case, the valid sorted elements still appear in order after the abnormal value.
- The invalid value
Fix Suggestion
Adjust the comparison count to avoid out-of-bounds access by initializing $t4 to nums - 1 (since we need n-1 comparisons per pass for n elements):
.text la $s0, elems lw $t4, nums subi $t4, $t4, 1 # Subtract 1 to get n-1 comparisons per pass
This ensures each pass only compares valid adjacent elements. Your descending sort will then output the expected result: 87 78 56 54 43 42 23 21 15 10 The end.
内容的提问来源于stack exchange,提问作者NgTriVien

