MIPS汇编实现期末成绩计算器运行异常问题求助
问题根因
你的程序连续输出多条成绩提示、运行逻辑异常,是以下几个明确的代码错误导致的:
- move指令操作数顺序写反:MIPS中
move 目的寄存器, 源寄存器,你两处赋值完全颠倒:- 调分值校验通过后写的
move $v0, $t1,是把初始值为0的t1覆盖了存用户输入的$v0,正确写法应为move $t1, $v0,把用户输入的调分值存入t1 - 原始成绩校验通过后写的
move $v0, $t0,是把初始值为0的t0覆盖了存用户输入的$v0,正确写法应为move $t0, $v0,把用户输入的原始成绩存入t0
这两个错误会导致你根本没拿到用户输入的有效值,t0/t1要么是初始0值要么是残留随机值,直接导致分数计算错误。
- 调分值校验通过后写的
- 分支跳转后缺少退出逻辑,代码顺序穿透执行:这是连续打印多条等级提示的直接原因。你用
bge跳转到对应等级的打印标签后,打印逻辑执行完没有跳转到程序出口,CPU会按地址顺序继续执行后面所有等级的打印代码——比如跳转到grade_a_plus打印完A+,会直接往下跑grade_a、grade_b_plus等所有后续标签的打印逻辑,直到代码段结束。 - 输入校验指令用错:成绩小于0的校验你用了
bltzal(小于0则跳转并链接,会无条件把返回地址写入$ra寄存器),你这里只需要判断小于0就重输,不需要保存返回地址,用普通blt指令即可,用bltzal会乱改$ra导致后续跳转跑飞。 - 分数判断链不完整,无合法退出路径:你只写了95分以上、90-94、85-89三个区间的判断,85分以下的B、C、D、F区间完全缺失;分数判断结束后写的
jr $31完全无效,因为$ra已经被bltzal破坏,且你没有写程序退出的系统调用,执行流会乱跳。 - 输出缺少换行:所有等级字符串后没有加换行打印,输出会挤在同一行。
修正后可运行代码
.data STR_MESSAGE1: .asciiz "Enter the grade: " STR_MESSAGE2: .asciiz "Enter the curve: " GRADEAPLUS: .asciiz "You earned A+" GRADEA: .asciiz "You earned A" GRADEBPLUS: .asciiz "You earned B+" GRADEB: .asciiz "You earned B" GRADECPLUS: .asciiz "You earned C+" GRADEC: .asciiz "You earned C" GRADEDPLUS: .asciiz "You earned D+" GRADED: .asciiz "You earned D" GRADEF: .asciiz "You earned F" NEW_LINE: .asciiz "\n" .text .globl main main: # 初始化阈值寄存器 li $t0, 0 # 存原始成绩 li $t1, 0 # 存调分值 li $t2, 100 # 成绩上限 li $t3, 2 # 调分下限 li $t4, 8 # 调分上限 li $t5, 0 # 存最终总分 curve_check: li $v0, 4 la $a0, STR_MESSAGE2 syscall li $v0, 5 syscall blt $v0, $t3, curve_check bgt $v0, $t4, curve_check move $t1, $v0 # 修正:把合法调分值存入t1 grade_check: li $v0, 4 la $a0, STR_MESSAGE1 syscall li $v0, 5 syscall blt $v0, $zero, grade_check # 修正:用普通blt替换bltzal,不修改ra bgt $v0, $t2, grade_check move $t0, $v0 # 修正:把合法原始成绩存入t0 score_add: addu $t5, $t0, $t1 # 补全所有分数区间判断 bge $t5, 95, grade_a_plus bge $t5, 90, grade_a bge $t5, 85, grade_b_plus bge $t5, 80, grade_b bge $t5, 75, grade_c_plus bge $t5, 70, grade_c bge $t5, 65, grade_d_plus bge $t5, 60, grade_d j grade_f # 每个等级打印完加换行,跳转到程序退出 grade_a_plus: li $v0, 4 la $a0, GRADEAPLUS syscall jal print_newline j exit grade_a: li $v0, 4 la $a0, GRADEA syscall jal print_newline j exit grade_b_plus: li $v0, 4 la $a0, GRADEBPLUS syscall jal print_newline j exit grade_b: li $v0, 4 la $a0, GRADEB syscall jal print_newline j exit grade_c_plus: li $v0, 4 la $a0, GRADECPLUS syscall jal print_newline j exit grade_c: li $v0, 4 la $a0, GRADEC syscall jal print_newline j exit grade_d_plus: li $v0, 4 la $a0, GRADEDPLUS syscall jal print_newline j exit grade_d: li $v0, 4 la $a0, GRADED syscall jal print_newline j exit grade_f: li $v0, 4 la $a0, GRADEF syscall jal print_newline j exit # 打印换行公共函数 print_newline: li $v0, 4 la $a0, NEW_LINE syscall jr $ra # 程序退出逻辑 exit: li $v0, 10 syscall
内容的提问来源于stack exchange,提问作者Aayush Gauba
相关产品推荐
相关产品推荐

