MIPS汇编使用beq指令时函数跳转异常的问题排查
MIPS中beq指令无法正确分支的问题排查与解决
问题根源
你的代码存在两个致命逻辑错误,直接导致beq分支完全失效:
- 字符值被地址覆盖:你先通过
li $s4, 'a'把字符'a'的ASCII值加载到寄存器,但紧接着执行move $s4, $a0——$a0是存储输入字符串的缓冲区地址,这直接把之前的字符值覆盖成了内存地址,$s5、$s7也被同样改成了同一个地址。 - 比较对象错误:$s6存储的是输入字符串的缓冲区地址,你用
beq $s6, $s4, choiceA比较的是两个内存地址(而非输入字符和目标字符)。因为$s4/$s5/$s7都是同一个地址,所以第一个beq永远成立,无论输入什么都会跳转到choiceA。
修复方案
1. 删掉错误的赋值指令
移除move $s4, $a0、move $s5, $a0、move $s7, $a0这三行,保留li $s4, 'a'这类正确的字符ASCII值赋值。
2. 正确读取输入的字符
用lb指令加载输入缓冲区的第一个字节(即用户输入的字符)到临时寄存器,再用这个寄存器和目标字符做比较。
3. 补充遗漏的syscall指令
你的choiceB和choiceC分支里漏了syscall,即使跳转成功也不会执行打印操作,必须补上。
修正后的完整代码
# 定义输入缓冲区(建议改名避免和字符串标签冲突) .data input_buf: .space 50 countMsg: .asciiz "Choice A selected\n" lessThanMsg: .asciiz "Choice B selected\n" divisibleMsg: .asciiz "Choice C selected\n" choiceWhatMsg: .asciiz "Invalid choice\n" .text .globl main main: # 读取字符串输入 li $v0, 8 la $a0, input_buf li $a1, 50 syscall # 读取输入的第一个字符 lb $t0, ($a0) # 加载目标字符的ASCII值 li $s4, 'a' li $s5, 'b' li $s7, 'c' # 分支判断 beq $t0, $s4, choiceA beq $t0, $s5, choiceB beq $t0, $s7, choiceC # 输入无效时跳转到choiceWhat j choiceWhat # 退出程序 li $v0, 10 syscall choiceWhat: li $v0,4 la $a0,choiceWhatMsg syscall j done choiceA: li $v0,4 la $a0,countMsg syscall j done choiceB: li $v0,4 la $a0,lessThanMsg syscall j done choiceC: li $v0,4 la $a0,divisibleMsg syscall j done done:
额外注意事项
- 原代码中缓冲区变量名
choice和打印字符串标签重名,会导致编译错误,建议改为input_buf这类独特名称。 - syscall 8读取字符串时会包含用户输入的换行符,如果需要处理空输入(仅回车),可以增加对换行符
'\n'的判断。
内容的提问来源于stack exchange,提问作者zedyjy
相关产品推荐
相关产品推荐

