C 为什么在MASM汇编中使用FPU x87指令集执行操作时会得到无意义的数字?

C 为什么在MASM汇编中使用FPU x87指令集执行操作时会得到无意义的数字?,c,assembly,x86,masm,fpu,C,Assembly,X86,Masm,Fpu,我最近开始学习汇编,现在正在学习FPU x86体系结构和FPU堆栈。我有两个简单的函数可以在摄氏度和华氏度之间转换,反之亦然 我研究了各种不同的指令,尝试了FPU指令的变体,包括自动执行POP操作的指令,并尝试通过调试器了解我看到的内容。到目前为止没有用 .386 .model flat, c .const r8_ftoc real8 0.5555555556 ;5/9 r8_ctof real8 1.8 ;9/5 i4_32 dword 32 .code fahrentoce

我最近开始学习汇编,现在正在学习FPU x86体系结构和FPU堆栈。我有两个简单的函数可以在摄氏度和华氏度之间转换,反之亦然

我研究了各种不同的指令,尝试了FPU指令的变体,包括自动执行
POP
操作的指令,并尝试通过调试器了解我看到的内容。到目前为止没有用

.386
.model flat, c

.const
  r8_ftoc real8 0.5555555556 ;5/9
  r8_ctof real8 1.8 ;9/5
  i4_32 dword 32
.code
  fahrentocel PROC
    push ebp
    mov ebp, esp
    fld[r8_ftoc]
    fld real8 ptr [ebp+8] ; load f 
    fild[i4_32] ; load 32    
    fsubp
    fmulp
    pop ebp
    ret
  fahrentocel ENDP

  celtofahren PROC
    push ebp
    mov ebp, esp
    fild real8 ptr [ebp+8] ; load c
    fmul[r8_ctof]
    fiadd[i4_32]
    pop ebp
    ret
  celtofahren endp
END
C代码:

extern "C" double fahrentocel(double temp);
extern "C" double celtofahren(double temp);

int main()
{
    double celsius = 30.0;
    double fahrenheit = 212.0;
    double output = fahrentocel(fahrenheit);
    printf("%lf", output);

}
我的华氏到摄氏度的输入是212.0,所以摄氏度的输出是100,我的摄氏到华氏度的转换是30.0,所以华氏度的结果应该是86


但是,对于这两个函数,我分别得到了562950和858993459。我没有收到任何错误代码,因此该函数似乎毫无例外地执行,这表明我编写代码的方式可能存在逻辑错误。

这里有几个问题。根据使用函数的C代码中的函数声明,即:

extern "C" double fahrentocel(double temp);
extern "C" double celtofahren(double temp);
这两个函数都采用
double
参数并返回
double
结果。对于接口来说,这很好,但您的
celtofahren
实现却表明了不同的情况:

fild real8 ptr [ebp+8] ; load c
在这里,您可以将函数的参数作为整数加载到FPU堆栈中,即使您自己已经指示C编译器函数采用双精度。因此,C编译器发出的代码将
double
推送到常规堆栈上,但由于
fild
指令,程序集将其作为常规整数读取。请注意,
fahrentocel
正确加载参数

其次,您向
printf
传递了一个错误的格式参数,对于
double
值,
d
用于整数。因此,

printf("%d", output);
应该成为

printf("%f", output);

我没有看到任何输出函数。您的输出表明您得到了
SDWORD
s作为输出,但您应该得到
DOUBLE
s。您确定输出函数显示的是
DOUBLE
s吗?您没有显示实际使用这些函数的任何代码,因此我们只能假设参数的类型。
fahrentocel
函数的参数是一个
double
,但是
celtofahren
的参数似乎是一个整数,因为它加载了一个
fild
。这是故意的吗?请发布生成完整的、可编译的、可运行的程序所需的所有其他代码,即。我已经添加了C代码,对此我深表歉意。谢谢你通知我@fuz
%f
是双精度的,
%Lf
是长双精度的,
%Lf
是编译器供应商想做的任何东西。嘿,丹尼尔,我已经通过将其打印为整数来修复它,我只传递整数,所以将其作为int加载似乎不是问题,但我想,如果我用十进制值传递温度,那将是一个问题,谢谢你指出。以后我会记住你的答案,以避免出现问题。非常感谢你的帮助!抱歉,如果这看起来像一个简单的错误,我的C是非常生锈。