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

MIPS字符存储与打印异常:反转大小写后无法输出最小ASCII字符

MIPS大小写反转程序打印最小字符异常问题定位

问题描述

我编写了一个MIPS程序,实现将用户输入的字符进行大小写反转,输出反转后的字符串以及该字符串中ASCII值最小的字符。但在打印最小字符时出现异常:使用syscall 11打印显示为方框,使用syscall 4打印则显示空行。已通过实时调试确认寄存器$s1中存有值,大小写反转后的字符串可正常打印,且findMin()循环运行次数正确,怀疑是访问值的方式有误,寻求问题定位帮助。

程序代码

main:   
#
# system call to prompt user for input
#
     la $a0,outpPrompt  # system call 4 for print string needs address of string in $a0
     li $v0,4       # system call 4 for print string needs 4 in $v0
     syscall    
#
# system call to store user input into string thestring
#
    li $v0,8        # system call 8 for read string needs its call number 8 in $v0
                    # get return values
    la $a0,varStr       # put the address of thestring buffer in $t0
    li $a1,32           # maximum length of string to load
        syscall
#
# system call to display "You entered the string: "
#
     la $a0,outpStr     # system call 4 for print string needs address of string in $a0
     li $v0,4       # system call 4 for print string needs 4 in $v0
     syscall    

     la $a0,varStr      # system call 4 for print string needs address of string in $a0
     li $v0,4       # system call 4 for print string needs 4 in $v0
     syscall

    jal revCase     # Invoking revCase, string stored in $a0 printed

# Exit gracefully from main()
         li   $v0, 10       # system call for exit
         syscall            # close file

revCase:
    
    la $t1, varStr      # Loading user input
    la $t2, varStrRev   # Designated output string
    
    revLoop:
        lb $t0, 0($t1)      # loads char of $t1 into $t0
        beqz $t0, doneRev       # when 0 is hit, ends the loop
        
        blt $t0, 'A', saveChar  # if $t0 < A then saveChar
        ble $t0, 'Z', lowerCase # if $t0 >= A and <= Z jump to lowerCase
        blt $t0, 'a', saveChar  # if $t0 < a then saveChar
        ble $t0, 'z', upperCase # if $t0 >= a and <= z jump to upperCase
        j saveChar      # if $t0 > z then saveChar
        
        upperCase:
        subi $t0, $t0, 32   # converts uppercase letter to lowercase letter
        j saveChar
        
        lowerCase:
        addi $t0, $t0, 32   # converts lowercase letter to uppercase letter
        j saveChar
        
        saveChar:
        sb $t0, 0($t2)      # character saved to $t2
        
        addi $t1, $t1, 1    # increment input
        addi $t2, $t2, 1    # increment output
        
    j revLoop           # continues the loop
    
    doneRev:
    sb $zero, 0($t2)    # adds a 0 to end of string
    la $v0, varStrRev   # Stores address of converted string into $v0

#
# This is the system call to display "Your string in reverse case is: "
     la $a0,outpStrRev  # system call 4 for print string needs address of string in $a0
     li $v0,4       # system call 4 for print string needs 4 in $v0
     syscall    
# system call to display the user input that is in reverse case saved in the varRevStr buffer
     la $a0,varStrRev   # system call 4 for print string needs address of string in $a0
     li $v0,4       # system call 4 for print string needs 4 in $v0
     syscall    

    move $s0, $ra
    jal findMin     # calls findMin, replaces $ra value

jr $s0          # Return to original function call address

findMin:
    la $t1, varStrRev       # Loading reverse input
    la $s1, varStrMin       # Designated output string
    
    minLoop:
        lb $t0, 0($t1)      # setting $t0 to first char of $t1
        beqz $t0, doneMin       # break loop when $t0 = 0
        
        blt $t0, $s1, lowestChar    # if current char < saved char, jump to lowestChar
        j nextChar      # if current char >= lowest char, jump to nextChar
        
        lowestChar:
        sb $t0, 0($s1)      # save lowest char to $s1
        j nextChar
        
        nextChar:
        addi $t1, $t1, 1    # increment to next char

    j minLoop           #continue loop
    doneMin:
#
# system call to display "The min ASCII character after reversal is:  "
     la $a0, outpStrMin     # system call 4 for print string needs address of string in $a0
     li $v0, 4      # system call 4 for print string needs 4 in $v0
     syscall    

    la $a0, varStrMin
    li $v0, 11  
    syscall

jr $ra              # Return to address in revCase

问题定位与修复

1. 最小值初始化缺失+比较逻辑错误

  • 问题:findMin函数中,la $s1, varStrMin加载的是变量地址,而非存储的字符值。第一次循环时varStrMin未初始化,且blt $t0, $s1是拿当前字符和地址数值比较,完全不符合逻辑,导致最小值计算错误。
  • 修复:进入循环前,先将反转字符串的第一个字符作为初始最小值存入varStrMin,且比较时要加载varStrMin中的字符值而非地址:
findMin:
    la $t1, varStrRev
    la $s1, varStrMin
    # 初始化最小值为第一个字符
    lb $t0, 0($t1)
    beqz $t0, doneMin       # 处理空字符串
    sb $t0, 0($s1)
    addi $t1, $t1, 1        # 跳过已初始化的第一个字符
    
    minLoop:
        lb $t0, 0($t1)
        beqz $t0, doneMin
        lb $t3, 0($s1)      # 加载当前存储的最小值
        blt $t0, $t3, lowestChar  # 拿当前字符和最小值比较

2. syscall调用参数错误

  • 问题:
    • syscall 11要求$a0存放单个字符的ASCII值,原代码la $a0, varStrMin加载的是地址,而非字符值,导致打印出地址对应的ASCII字符(通常是不可见字符,显示为方框)。
    • syscall 4要求$a0存放以null结尾的字符串地址,原代码中varStrMin只存储了单个字符,没有添加结束符,导致打印空行或乱码。
  • 修复:
    • 使用syscall 11时,加载varStrMin中的字符值到$a0:lb $a0, 0(varStrMin)
    • 使用syscall 4时,在varStrMin的字符后添加null结束符:sb $zero, 1($s1)

修正后的findMin函数

findMin:
    la $t1, varStrRev       # 加载反转后的字符串地址
    la $s1, varStrMin       # 加载存储最小值的变量地址
    
    # 初始化最小值为第一个字符
    lb $t0, 0($t1)
    beqz $t0, doneMin       # 空字符串直接退出
    sb $t0, 0($s1)
    addi $t1, $t1, 1        # 移动到下一个字符
    
    minLoop:
        lb $t0, 0($t1)      # 读取当前字符
        beqz $t0, doneMin   # 遇到结束符退出
        
        lb $t3, 0($s1)      # 取出当前最小值
        blt $t0, $t3, lowestChar    # 当前字符更小则更新
        j nextChar
        
        lowestChar:
        sb $t0, 0($s1)      # 保存新的最小值
        
        nextChar:
        addi $t1, $t1, 1    # 移动到下一个字符
    j minLoop
    
    doneMin:
    sb $zero, 1($s1)        # 添加字符串结束符,支持syscall 4打印
    # 打印提示信息
    la $a0, outpStrMin
    li $v0, 4
    syscall    
    # 用syscall 11打印单个字符
    lb $a0, 0(varStrMin)
    li $v0, 11  
    syscall

jr $ra

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:50:54