1

我是汇编编程的新手,作为更大程序的一部分,我需要将浮点值传递给另一个 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,海湾合作委员会-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   $4, %esp
     leave
     ret

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

  • 我的第一个问题是,ext_func 是否缺少浮点堆栈(ST)上的一些数据,因此无法生成浮点值?(我知道你没有被调用函数,但函数的作用无关紧要?)
  • 其次,如果编译器需要浮点值,编译器是否总是去 f 堆栈获取浮点值,或者是否可以从内存堆栈中读取它们?
  • 第三,这里还有什么我想念的吗?如果我
printf("%f", a);     //3.140000  
printf("%f", str);      //3.140000

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

4

1 回答 1

3

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

请注意,ext_funcvoid不返回任何东西,但您声明tester为返回double......不清楚您想要返回什么,我会假设您想要原件d返回(无论出于何种原因)。

因此,可能的实现可能是:

     .globl tester
tester:
     subl   $12, %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   $12, %esp      # cleanup stack
     ret
于 2015-05-19T11:35:40.520 回答