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
关键说明
- 调用约定必须匹配:
crt_printf是C标准库函数,采用cdecl约定,因此汇编代码需设置.model flat, c,否则会出现栈不平衡或参数解析错误。 - 格式符与参数类型必须对应:
%f仅对应double类型,若使用float则需先转换为double再传递。
内容的提问来源于stack exchange,提问作者LOTR 315
相关产品推荐
相关产品推荐

