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

MASM中使用crt_printf输出浮点数显示0.000000的问题

MASM调用crt_printf输出浮点数显示0.000000的问题解决

问题场景

在MASM汇编环境中调用msvcrt.lib的crt_printf函数输出浮点数时,目标数值未正常显示,取而代之的是0.000000,相关代码如下:

.386
.model flat, stdcall    
option casemap :none   

include     \masm32\include\kernel32.inc 
include     \masm32\include\windows.inc 
includelib  \masm32\lib\kernel32.lib 
 
include     \masm32\include\user32.inc 
includelib  \masm32\lib\user32.lib      

include \masm32\include\msvcrt.inc 
includelib  \masm32\lib\msvcrt.lib

.data
fmto db "%f",0 

n dd 0.2

.code
main:
    mov eax, n
    invoke crt_printf, ADDR fmto, eax, 0
    invoke ExitProcess, 0

end main

错误原因

  • 调用约定不匹配:crt_printf采用cdecl调用约定,而代码中设置的stdcall约定在参数传递、栈清理逻辑上与cdecl不符,会导致参数解析错误。
  • 浮点数类型不匹配:%f格式符要求接收8字节的double类型数据,但代码中n定义为dd(4字节float类型),直接传递float的二进制值无法被printf正确解析。
  • 参数传递方式错误:直接通过eax传递float值的方式不符合printf对浮点参数的处理逻辑,x86环境下printf会将浮点参数视为double类型处理。

修正方案

方案1:直接使用double类型参数(最简)

将浮点数定义为double类型,并切换到cdecl调用约定,代码如下:

.386
.model flat, c    ; 切换为cdecl调用约定,适配crt_printf
option casemap :none   

include     \masm32\include\kernel32.inc 
include     \masm32\include\windows.inc 
includelib  \masm32\lib\kernel32.lib 
 
include     \masm32\include\user32.inc 
includelib  \masm32\lib\user32.lib      

include \masm32\include\msvcrt.inc 
includelib  \masm32\lib\msvcrt.lib

.data
fmto db "%f",0 
n dq 0.2  ; 定义为8字节的double类型,匹配%f格式要求

.code
main:
    invoke crt_printf, ADDR fmto, n  ; cdecl约定下,invoke自动处理参数压栈
    invoke ExitProcess, 0

end main

方案2:保留float类型并转换为double传递

如果需要保留float类型的变量,可通过FPU将其转换为double后再传递:

.386
.model flat, c    
option casemap :none   

include     \masm32\include\kernel32.inc 
include     \masm32\include\windows.inc 
includelib  \masm32\lib\kernel32.lib 
 
include     \masm32\include\user32.inc 
includelib  \masm32\lib\user32.lib      

include \masm32\include\msvcrt.inc 
includelib  \masm32\lib\msvcrt.lib

.data
fmto db "%f",0 
n dd 0.2  ; 保留float类型变量

.code
main:
    sub esp, 8          ; 为double参数预留8字节栈空间
    fld dword ptr [n]   ; 将float加载到FPU栈顶
    fstp qword ptr [esp] ; 将FPU中的值转换为double并存储到栈上
    push ADDR fmto      ; 压入格式串地址
    call crt_printf     ; 调用printf
    add esp, 12         ; 清理栈:8(double)+4(格式串)=12字节

    invoke ExitProcess, 0

end main

关键说明

  1. 调用约定必须匹配:crt_printf是C标准库函数,采用cdecl约定,因此汇编代码需设置.model flat, c,否则会出现栈不平衡或参数解析错误。
  2. 格式符与参数类型必须对应:%f仅对应double类型,若使用float则需先转换为double再传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:46:18