MIPS汇编中浮点数与1比较失效问题排查
问题根源与修正方案
核心错误分析
你的代码存在两个关键问题,导致无法正确过滤<=1的浮点数:
- 浮点数比较逻辑错误:你用
mfc1 $t0, $f0将浮点寄存器的值直接转到整数寄存器,再用整数比较指令bgt $t0,1判断。但单精度浮点数采用IEEE754二进制格式,直接转成整数后的值和实际浮点值完全无关,这就是为什么只能过滤负数(负数的浮点格式符号位为1,转成整数是负数,会被bgt $t0,1跳过),但正数里的0.5、1.0等<=1的数值会被误判为符合条件。 - 输出计数逻辑错误:原代码用输入的
n作为输出循环次数,但实际入栈的是过滤后的数值,数量可能小于n,会导致读取栈中无效数据。
另外你尝试的cvt.s.w指令报错,是因为该指令是整数转单精度浮点数,操作数必须是浮点寄存器,你可能错误使用了整数寄存器作为操作数,导致类型不匹配。
修正步骤
1. 正确实现浮点数比较
- 在数据段定义单精度常量1.0:
.data one_float: .float 1.0 - 程序初始化时将该常量加载到浮点寄存器(比如$f1):
main: # ... 原有代码 ... l.s $f1, one_float # 加载1.0到$f1 - 替换原有的错误比较逻辑,使用浮点比较指令:
input_loop: # ... 原有输入代码 ... li $v0, 6 # 读取浮点数到$f0 syscall # 比较输入值$f0和1.0$f1:如果$f0 > 1.0则入栈 c.lt.s $f1, $f0 # 当1.0 < 输入值时,条件为真 bc1t input_loop1 # 条件成立则跳转入栈逻辑 j input_loop # 否则重新输入
2. 修正栈操作与输出计数
- 直接将浮点寄存器的值存入栈(无需转整数):
input_loop1: addi $sp, $sp, -4 s.s $f0, 0($sp) # 直接存储浮点数到栈 li $v0, 4 la $a0, strNewLine syscall addiu $s1, $s1, 1 addiu $s2, $s2, 1 # 统计入栈的有效数值数量 ble $s1, $s0, input_loop j output_loop_init - 初始化统计变量:在
input_loop_init中添加li $s2, 0 - 输出时使用有效数值数量作为循环次数:
output_loop_init: move $s1, $s2 # 用实际入栈数量作为输出次数 j output_loop - 输出时直接从栈读取浮点数:
output_loop: # ... 原有输出前缀代码 ... l.s $f12, 0($sp) # 直接读取栈中的浮点数到$f12 addi $sp, $sp, 4 li $v0, 2 syscall # ... 原有换行代码 ... addi $s1, $s1, -1 bgt $s1, $zero, output_loop j exit
完整修正代码
.data strN: .asciiz "n=? \n" strEingabe: .asciiz "te Zahl = ? \n" strAusgabe: .asciiz "te Zahl = \n" strNewLine: .asciiz "\n" strNegative: .asciiz "\n Fehler: Ungültiger Wert für n!\n" one_float: .float 1.0 # 定义单精度1.0常量 .text .globl main main: li $v0, 4 la $a0, strN syscall li $v0, 5 syscall move $s0, $v0 # $s0 = n li $v0, 4 la $a0, strNewLine syscall l.s $f1, one_float # 加载1.0到$f1,用于后续比较 bgtz $s0, input_loop_init j negative input_loop_init: li $s1, 1 li $s2, 0 # $s2统计有效入栈的数值数量 j input_loop input_loop: li $v0, 1 move $a0, $s1 syscall li $v0, 4 la $a0, strEingabe syscall li $v0, 6 # 读取浮点数,保存到$f0 syscall # 比较$f0和1.0,仅当$f0>1.0时入栈 c.lt.s $f1, $f0 bc1t input_loop1 j input_loop input_loop1: addi $sp, $sp, -4 s.s $f0, 0($sp) # 直接存储浮点数到栈 li $v0, 4 la $a0, strNewLine syscall addiu $s1, $s1, 1 addiu $s2, $s2, 1 # 有效数量+1 ble $s1, $s0, input_loop j output_loop_init output_loop_init: move $s1, $s2 # 使用实际有效数量作为输出次数 j output_loop output_loop: li $v0, 1 move $a0, $s1 syscall li $v0, 4 la $a0, strAusgabe syscall l.s $f12, 0($sp) # 直接从栈读取浮点数 addi $sp, $sp, 4 li $v0, 2 syscall li $v0, 4 la $a0, strNewLine syscall addi $s1, $s1, -1 bgt $s1, $zero, output_loop j exit negative: li $v0, 4 la $a0, strNegative syscall j exit exit: li $v0, 10 syscall
内容的提问来源于stack exchange,提问作者Matze
相关产品推荐
相关产品推荐

