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要求$a0存放单个字符的ASCII值,原代码
- 修复:
- 使用syscall 11时,加载
varStrMin中的字符值到$a0:lb $a0, 0(varStrMin) - 使用syscall 4时,在
varStrMin的字符后添加null结束符:sb $zero, 1($s1)
- 使用syscall 11时,加载
修正后的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
相关产品推荐
相关产品推荐

