在程序集 x86 x87 中使用 float 调用函数

call function with float in assembly x86 x87

我是汇编编程的新手,作为一个更大程序的一部分,我需要将浮点值传递给另一个 C 函数。我有一个从我的测试程序到我的汇编函数的调用,它只将参数压入正确的堆栈,并调用第二个 C 函数。

我的 C 测试函数:

 extern void ext_func(char *result, double d); // C function
 extern double tester(char *str, float d);

 double a = tester(str, 3.14)
 printf("%s\n", str);       // Resulting in '0.000000'

 // doing some fancy stuff with the float value and puts in result
 ext_func(str, 3.14);       // gives str = "3.140000"

x86,gcc -m32:

     .globl tester
tester:
     pushl  %ebp        # Standard
     movl   %esp, %ebp  #
     flds   12(%ebp)    # Push second parameter on stack
     pushl  8(%ebp)
     call   ext_func
     addl   , %esp
     leave
     ret

我认为当 ext_funct 期待双倍时我只推 32 位有问题。但我尝试了 fldl、fld1、fildl、fldl 12 和 16(%ebp),以及其他一些 "fun"。

printf("%f", a);     //3.140000  
printf("%f", str);      //3.140000

但另一种方式 a 给出以 000000 结尾的大负数(100 位左右)。

32 位约定使用cpu 堆栈来传递浮点参数。它只使用 fpu 堆栈 returning 它们。是的,您应该按照您提供的原型将 32 位浮点数转换为 64 位双精度数。

请注意 ext_funcvoid,也就是说它没有 return 任何东西,但是您将 tester 声明为 returning double ...不清楚你想要什么return,我假设你想要原来的d(无论出于何种原因)。

因此,可能的实施方式可能是:

     .globl tester
tester:
     subl   , %esp      # allocate space for outgoing arguments
     movl   16(%esp), %eax # fetch our first argument (str)
     movl   %eax, (%esp)   # store as first outgoing argument
     flds   20(%esp)       # Fetch our second argument as float
     fstpl  4(%esp)        # store it as second outgoing argument as double
     call   ext_func
     flds   20(%esp)       # load d as return value
     addl   , %esp      # cleanup stack
     ret