MIPS汇编回文检测代码异常求助:正确回文误判为NO
回文检测MIPS汇编代码功能异常排查
我写的MIPS汇编回文检测代码功能异常:
- 输入回文"racecar"时返回"NO"
- 输入非回文"gn."时返回"YES"
- 输入"night."返回"NO"
我调试了回文检测模块但没找到问题,不确定是不是poll_UART模块的问题,以下是完整代码:
.org 0x10000000 # Initializations # NOTE: You may add initializations after line 10, but please do not # remove or change the initializations to $sp, $s0, $s1, or $s2 li $sp, 0x10fffffc # Starting address of empty stack li $s0, 0xf0000000 # UART base address li $s1, array_ptr # Array head pointer li $s2, array_ptr # Array tail pointer li $t8 0x00000000 #################################################################### # Do not make changes to the jump to main, the allocation of # memory for the array, or the main loop #################################################################### j main nop array_ptr: # Label pointing to 100 word array .space 100 main: jal poll_UART nop jal period_check nop jal space_check nop jal case_check nop jal array_push nop j main nop #################################################################### # ****************************************************************** #################################################################### # The "poll_UART" function should poll the status register of the UART. # If the 2^1 bit position (ready bit) is set to 1 then it # should copy the receive buffer's value into $v0 and send # a clear status command (2^1) to the command register before # returning (a return statement is already included). In order to # receive full credit, $s0 must contain the base address of the UART # and must be used with the appropriate offsets to access UART # registers and buffers poll_UART: lw $t1, 4($s0) li $t2, 0b10 and $t3, $t1, $t2 beq $t3, $0, main nop lw $v0, 8($s0) sw $t2, 0($s0) jr $ra nop # The "period_check" function should check if the current character ($v0) # is a period ("."). If it is a period then the function should go to the # label, "palindrome_check". If the character is not a period then it # should use the included return. period_check: li $t0, 0x2E beq $v0, $t0, palindrome_check nop jr $ra nop # The "space_check" function should check if the current character ($v0) # is a space (" "). If it is then it should jump to "main" so # that it skips saving the space character. If not it should # use the included return. space_check: li $t4, 0x20 beq $t4, $v0, main nop jr $ra nop # The "case_check" function should perform a single inequality check. # If the current character ($v0) is greater than the ASCII value of 'Z', # which indicates the current character is lowercase, then it should convert # the value of $v0 to the uppercase equivalent and then return. If the # current character ($v0) is already uppercase (meaning the inequality # mentioned before was not true) then the function should return without # performing a conversion. case_check: li $t5, 0x5A slt $t6, $v0, $t5 li $t7, 1 beq $t6, $t7, change_uppercase change_uppercase: addiu $v0, $v0, -32 jr $ra nop # The "array_push" function should save the current character ($v0) to the # current location of the tail pointer, $s2. Then it should increment the # tail pointer so that it points to the next element of the array. Last # it should use the included return statement. array_push: sw $v0, 0($s2) addiu $s2, $s2, 4 jr $ra nop # The "palindrome_check" subroutine should be jumped to by the period # check function if a period is encountered. This subroutine should contain # a loop that traverses the array from the front towards the back (using the # head pointer, $s1) and from the back towards the front(using the tail # pointer, $s2). If the string is a palindrome then as the array is traversed # the characters pointed to should be equal. If the characters are not equal # then the string is not a palindrome and the print function should be used # to print "No". If the pointers cross (i.e. the head pointer's address is # greater than or equal to the tail pointer's address) and the compared # characters are equal then the string is a palindrome and "Yes" should be # printed. # # Remember to restore the head and tail pointers to the first element # of the array before the subroutine jumps back to main to begin processing the # next string. Also, keep in mind that because the tail pointer is updated at # the end of "array_push" it technically points one element past the last # character in the array. You will need to compensate for this by either # decrementing the pointer once at the start of the array or using an offset # from this pointer's address. palindrome_check: addiu $s2, $s2, -8 move $s3, $s1 subu $s4, $s2, $s3 beq $s4, $0, palindrome nop check_loop: lw $s5, 0($s3) lw $s6, 0($s2) bne $s6, $t5, not_palindrome nop adjust_pointers: addiu $s2, $s2, -4 addiu $s3, $s3, 4 slt $t8, $s3, $s2 bne $t8, $0, check_loop nop j palindrome nop palindrome: li $a0, 1 call project3_print move $s2, $s1 j main nop not_palindrome: li $a0, 0 call project3_print move $s2, $s1 j main nop
问题点分析与修复
1. 核心错误:回文对比逻辑完全错误
palindrome_check里的bne $s6, $t5, not_palindrome是把尾部字符和$t5('Z'的ASCII值)对比,而不是和头部字符$s5对比,这直接导致判断逻辑完全失效。
2. 大小写转换逻辑颠倒
case_check里用slt $t6, $v0, $t5判断字符是否小于'Z',然后执行转大写,这和需求相反:应该是字符大于'Z'(小写)才转大写,现在会把大写字母、数字等都错误转成不可见字符,导致回文对比不匹配。
3. 回文检测指针初始位置错误
array_push执行后s2指向最后一个字符的下一个位置,原代码减8会跳过最后一个有效字符,应该只减4。
4. 函数返回逻辑破坏调用栈
poll_UART和space_check中直接跳回main,跳过了jr $ra,导致返回地址丢失,后续函数调用混乱。
修复后的代码
.org 0x10000000 # Initializations # NOTE: You may add initializations after line 10, but please do not # remove or change the initializations to $sp, $s0, $s1, or $s2 li $sp, 0x10fffffc # Starting address of empty stack li $s0, 0xf0000000 # UART base address li $s1, array_ptr # Array head pointer li $s2, array_ptr # Array tail pointer li $t8, 0x00000000 #################################################################### # Do not make changes to the jump to main, the allocation of # memory for the array, or the main loop #################################################################### j main nop array_ptr: # Label pointing to 100 word array .space 100 main: jal poll_UART nop jal period_check nop jal space_check nop jal case_check nop jal array_push nop j main nop #################################################################### # ****************************************************************** #################################################################### # poll_UART 修复:未就绪时直接返回,不破坏调用栈 poll_UART: lw $t1, 4($s0) li $t2, 0b10 and $t3, $t1, $t2 beq $t3, $0, poll_UART_return nop lw $v0, 8($s0) sw $t2, 0($s0) poll_UART_return: jr $ra nop period_check: li $t0, 0x2E beq $v0, $t0, palindrome_check nop jr $ra nop # space_check 修复:检测到空格时先返回再跳main space_check: li $t4, 0x20 beq $v0, $t4, space_check_return nop jr $ra nop space_check_return: j main nop # case_check 修复:仅小写字母转大写 case_check: li $t5, 0x5A # 'Z'的ASCII值 slt $t6, $t5, $v0 # 判断字符是否大于'Z'(小写) beq $t6, $0, case_check_return # 非小写直接返回 nop change_uppercase: addiu $v0, $v0, -32 # 转大写 case_check_return: jr $ra nop array_push: sw $v0, 0($s2) addiu $s2, $s2, 4 jr $ra nop # palindrome_check 修复:指针位置、对比逻辑 palindrome_check: addiu $s2, $s2, -4 # 回到最后一个有效字符 move $s3, $s1 # 头部遍历指针 check_loop: lw $s5, 0($s3) # 取头部字符 lw $s6, 0($s2) # 取尾部字符 bne $s5, $s6, not_palindrome # 字符不相等则非回文 nop # 检查指针是否交叉/相遇 slt $t8, $s3, $s2 beq $t8, $0, palindrome nop adjust_pointers: addiu $s2, $s2, -4 # 尾部指针左移 addiu $s3, $s3, 4 # 头部指针右移 j check_loop nop palindrome: li $a0, 1 call project3_print move $s2, $s1 # 重置指针 j main nop not_palindrome: li $a0, 0 call project3_print move $s2, $s1 # 重置指针 j main nop
内容的提问来源于stack exchange,提问作者mkj
相关产品推荐
相关产品推荐

