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

基于PLPTool 5.2的MIPS汇编回文检查程序跳转异常排查求助

问题

我正在完成课程作业,使用PLPTool 5.2编写MIPS汇编程序,该程序需通过UART接收字符串,检查是否为回文后调用打印函数输出“Yes”或“No”。我已填充完给定的模板代码,程序编译无错误,但逐行调试发现,即使通过UART输入正确内容,程序也始终无法跳转到palindrome_check标签。以下是我的代码:

.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



####################################################################
# 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 $t0, 4($s0)
    li $t1, 0b10
    and $t2, $t0, $t1
    beq $t2, $zero, poll_UART
    nop
    
    lw $v0, 8($s0)
    sw $t1, 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 make a nested function call to palindrome_check

period_check:


    li $t3, 0x2E
    beq $v0, $t3, 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, upper_case
    nop
    jr $ra
    nop
          

    upper_case:
    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, -4
    scan:
    lw $t8, 0($s1)
    lw $t9, 0($s2)
    bne $t8, $t9, FALSE
    nop

    addiu $s2, $s2, -4
    addiu $s1, $s1 4
    slt $t7, $s2, $s1
    beq $t7, $zero, scan
    nop

    j TRUE
    nop

    TRUE:
    li $a0, 1
    call project3_print
    li $s1, array_ptr
    li $s2, array_ptr
    j main 
    nop

    FALSE:
    li $a0, 0
    call project3_print
    li $s1, array_ptr
    li $s2, array_ptr
    j main
    nop
排查方法
  • 验证poll_UART的字符读取正确性:在poll_UART返回后,立即查看寄存器$v0的值,确认输入句号时是否读取到了ASCII值0x2E。如果值不对,检查UART寄存器偏移是否符合PLPTool的规范,比如接收缓冲区的偏移是否真的是8($s0),状态寄存器的偏移是否是4($s0)。
  • 检查period_check的分支触发情况:在period_check的beq $v0, $t3, palindrome_check指令处设置断点,输入句号后,查看$v0和$t3(0x2E)是否相等,以及分支是否被触发(调试器会显示分支是否taken)。如果分支未触发,说明$v0的值不正确,回到poll_UART排查读取逻辑。
  • 确认主循环的执行流程:当输入句号时,period_check的跳转应该直接跳到palindrome_check,跳过后续的space_check、case_check等调用。调试时跟踪程序计数器(PC),确认执行beq后PC是否跳转到palindrome_check的地址。
  • 检查palindrome_check标签的有效性:查看汇编后的机器码,确认beq指令的跳转目标地址是否与palindrome_check的实际地址一致,避免因汇编地址计算错误导致跳转失败。
  • 排除其他函数的干扰:暂时注释掉主循环中period_check之后的函数调用,单独测试period_check的跳转是否正常,排除后续函数对寄存器或执行流程的意外影响。

内容的提问来源于stack exchange,提问作者Jonathan Alvaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:05:53