You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编FPU浮点运算问题:小数乘10的幂结果异常求助

x86汇编浮点运算异常问题排查与修复

问题描述

编写x86汇编程序实现:将用户输入的小数按指定精度(1-4)乘以对应10的幂,示例输入1.23456、精度2时预期结果为123.456。但运行后结果要么是科学计数法格式,要么显示为NaN,尝试修改变量类型、调整FPU栈加载顺序均未解决,对汇编浮点运算经验较少。

原始代码

INCLUDE Irvine32.inc

.DATA
    inputPrompt         BYTE "Enter a number with at least 5 decimal places: ", 0
    precisionPrompt     BYTE "Enter a precision value (1, 2, 3, or 4): ", 0
    multiplyValueMsg    BYTE "Multiply Value: ", 0
    userInput           REAL4 0.0               ; 存储用户输入的浮点值
    precisionValue      DWORD 0                 ; 存储精度值
    multiplyValue       DWORD 0                 ; 对应10的幂值(10/100/1000/10000)
    resultMsg           BYTE "   Result: ", 0
    resultValue         REAL4 0.0               ; 存储运算结果

.CODE

MAIN PROC
    mov edx, OFFSET inputPrompt                 
    call WriteString                            

    mov edx, OFFSET userInput                   
    mov ecx, 101                                
    call ReadString                              ; 错误:用ReadString读取浮点输入

    ; 读取精度值
    mov edx, OFFSET precisionPrompt             
    call WriteString                            
    call ReadInt                                
    mov precisionValue, eax                     

    ; 计算multiplyValue
    mov eax, precisionValue                     
    cmp eax, 1                                  
    je precision1                               
    cmp eax, 2                                  
    je precision2                               
    cmp eax, 3                                  
    je precision3                               
    cmp eax, 4                                  
    je precision4                               
    jmp next                                    

precision1:
    mov multiplyValue, 10                       
    jmp next                                    

precision2:
    mov multiplyValue, 100                      
    jmp next                 

precision3:
    mov multiplyValue, 1000                     
    jmp next                 

precision4:
    mov multiplyValue, 10000                    
    jmp next                     

next:
    ; 显示multiplyValue
    mov eax, multiplyValue                      
    mov edx, OFFSET multiplyValueMsg            
    call WriteString                            
    call WriteDec                               

    ; 浮点运算部分
    fld userInput                               
    fild dword ptr [multiplyValue]              
    fmul                                        
    fstp dword ptr resultValue                  

    ; 显示结果
    mov edx, OFFSET resultMsg
    call WriteString                            
    fld resultValue                             
    call WriteFloat                             ; 默认格式会出现科学计数法

MAIN ENDP

END MAIN

核心问题与修复方案

1. 输入读取错误(导致NaN的根本原因)

ReadString是将用户输入的字符直接存入内存,但userInput是REAL4浮点类型,内存里的字符数据不是合法的浮点值,后续FPU加载后自然会出现NaN。

修复:替换为Irvine32库的ReadFloat函数,它会自动解析用户输入的字符串为浮点值:

; 替换原ReadString的代码块
mov edx, OFFSET inputPrompt                 
call WriteString                            
call ReadFloat       ; 读取用户输入的浮点值到FPU栈顶(ST0)
fstp userInput       ; 将ST0的值存入userInput变量

2. 显示格式问题(科学计数法)

WriteFloat默认会根据数值大小自动切换科学计数法,需要通过设置FPU控制字强制使用定点数格式,并指定显示精度。

修复:在显示结果前添加FPU控制字设置:

; 在.data段添加控制字定义
fpu_control_word    DWORD 0x037F ; FPU控制字:定点格式、6位小数精度、禁用异常

; 在调用WriteFloat前插入以下代码
fldcw fpu_control_word

完整修复后代码

INCLUDE Irvine32.inc

.DATA
    inputPrompt         BYTE "Enter a number with at least 5 decimal places: ", 0
    precisionPrompt     BYTE "Enter a precision value (1, 2, 3, or 4): ", 0
    multiplyValueMsg    BYTE "Multiply Value: ", 0
    userInput           REAL4 0.0               
    precisionValue      DWORD 0                 
    multiplyValue       DWORD 0                 
    resultMsg           BYTE "   Result: ", 0
    resultValue         REAL4 0.0               
    fpu_control_word    DWORD 0x037F ; FPU控制字:定点格式、6位小数

.CODE

MAIN PROC
    mov edx, OFFSET inputPrompt                 
    call WriteString                            
    call ReadFloat       ; 读取浮点输入到ST0
    fstp userInput       ; 存储到userInput

    ; 读取精度值
    mov edx, OFFSET precisionPrompt             
    call WriteString                            
    call ReadInt                                
    mov precisionValue, eax                     

    ; 计算multiplyValue
    mov eax, precisionValue                     
    cmp eax, 1                                  
    je precision1                               
    cmp eax, 2                                  
    je precision2                               
    cmp eax, 3                                  
    je precision3                               
    cmp eax, 4                                  
    je precision4                               
    jmp next                                    

precision1:
    mov multiplyValue, 10                       
    jmp next                                    

precision2:
    mov multiplyValue, 100                      
    jmp next                 

precision3:
    mov multiplyValue, 1000                     
    jmp next                 

precision4:
    mov multiplyValue, 10000                    
    jmp next                     

next:
    ; 显示multiplyValue
    mov eax, multiplyValue                      
    mov edx, OFFSET multiplyValueMsg            
    call WriteString                            
    call WriteDec                               
    call Crlf

    ; 浮点运算
    fld userInput                               
    fild dword ptr [multiplyValue]              
    fmul                                        
    fstp dword ptr resultValue                  

    ; 显示结果(设置FPU格式)
    mov edx, OFFSET resultMsg
    call WriteString                            
    fld resultValue                             
    fldcw fpu_control_word ; 应用定点格式设置
    call WriteFloat                             
    call Crlf

MAIN ENDP

END MAIN

验证效果

输入1.23456、精度2时,程序会输出Multiply Value: 100和Result: 123.456001(因REAL4精度限制有微小误差,若要更精确可改用REAL8类型)。

内容的提问来源于stack exchange,提问作者MadTragic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:44:57