You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:15:34