MIPS汇编华氏转摄氏数组转换器出错,求排查FtoC函数问题
MIPS汇编华氏转摄氏转换器错误修复
问题核心错误点
你遇到的输出异常(0.0 0.0 NaN NaN 0.0)是由三个关键错误导致的:
- 错误加载浮点数数组元素:使用
lw(整数加载指令)读取.float类型数组,会将浮点数的二进制编码当作整数解析,后续转成浮点数时必然出错。 - 整数转浮点数未做类型转换:直接用
mtc1将整数(如32、5、9)传入浮点寄存器,但未执行cvt.s.w转换,导致浮点寄存器中存储的是整数二进制而非正确的浮点数表示。 - 不必要的浮点数转整数操作:转换后的摄氏温度是浮点数,却用
cvt.w.s转成整数再存入.float数组,破坏了浮点数编码,后续读取时出现NaN或0。
修正后的完整代码
.data List_F: .float 1.5, 0, -5, -12, 1 List_C: .float 0,0,0,0,0 size: .word 5 startString: .asciiz "Converting the following Fahrenheit to Celsius \n" celsiusDisplay: .asciiz "\n\nTemperatures in Celsius \n" newLine: .asciiz "\n" .text j main FtoC: add $sp, $sp, -4 # 分配栈空间 sw $ra, 0($sp) # 保存返回地址 li $t0, 0 # 循环计数器i lw $t1, size # 加载数组长度 # 初始化转换所需的浮点数常量 li $t6, 32 mtc1 $t6, $f6 cvt.s.w $f6, $f6 # 将整数32转为浮点数32.0 li $t7, 5 mtc1 $t7, $f2 cvt.s.w $f2, $f2 # 整数5转为浮点数5.0 li $t8, 9 mtc1 $t8, $f3 cvt.s.w $f3, $f3 # 整数9转为浮点数9.0 div.s $f7, $f2, $f3 # 计算5/9的浮点数结果 For: beq $t0, $t1, endFor # 循环终止条件:i == size sll $t3, $t0, 2 # 计算数组元素偏移量(每个float占4字节) l.s $f0, List_F($t3) # 正确加载单精度浮点数元素 sub.s $f0, $f0, $f6 # F - 32.0 mul.s $f4, $f0, $f7 # (F-32)*5/9 s.s $f4, List_C($t3) # 直接将浮点数结果存入目标数组 add $t0, $t0, 1 # 计数器自增 j For endFor: lw $ra, 0($sp) # 恢复返回地址 add $sp, $sp, 4 # 释放栈空间 jr $ra # 返回主函数 main: li $t0, 0 # 循环计数器i lw $t1, size # 加载数组长度 la $a0, startString jal displayStartString forFahrenheit: beq $t0, $t1, endFahrDisplay sll $t3, $t0, 2 l.s $f12, List_F($t3) # 正确加载浮点数用于打印 jal displayFahrenheit la $a0, newLine jal displayNewLine add $t0, $t0,1 j forFahrenheit endFahrDisplay: jal FtoC la $a0, celsiusDisplay jal displayCelsiusString li $t0, 0 # 重置计数器 forCelsius: beq $t0, $t1, endCelsiusDisplay sll $t3, $t0, 2 l.s $f12, List_C($t3) # 正确加载转换后的浮点数 jal displayCelsius add $t0, $t0,1 la $a0, newLine jal displayNewLine j forCelsius endCelsiusDisplay: la $a0, newLine jal displayNewLine jal endProgram displayNewLine: li $v0, 4 syscall jr $ra displayFahrenheit: li $v0, 2 syscall jr $ra displayCelsius: li $v0, 2 # 打印浮点数的系统调用 syscall jr $ra displayCelsiusString: li $v0, 4 syscall jr $ra displayStartString: li $v0, 4 syscall jr $ra endProgram: li $v0, 10 syscall jr $ra
修正细节说明
- 浮点数指令替换:将操作
.float数组的lw/sw全部替换为l.s/s.s,确保正确处理单精度浮点数的二进制编码。 - 补全整数转浮点数步骤:所有
mtc1传入整数后,添加cvt.s.w指令,将整数二进制转换为对应的单精度浮点数。 - 移除冗余类型转换:删除
cvt.w.s和mfc1指令,直接用s.s将浮点数结果存入目标数组,保留完整的浮点数精度信息。
内容的提问来源于stack exchange,提问作者cmm32
相关产品推荐
相关产品推荐

