call function with float in assembly x86 x87

♀尐吖头ヾ 提交于 2019-12-11 12:12:52

问题


I'm new to assembly programming and, as a part of a bigger program I have need to pass floating point values to another C-function. I have a call from my test program to my assembly function, that only pushes the parameters on the right stack, and calls a second C function.

My C test function:

 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   $4, %esp
     leave
     ret

I think theres a problem with me only pushing 32 bit when ext_funct expecting double. But I tried to the fldl, fld1, fildl, fldl 12 and 16(%ebp), and some of the other for "fun".

  • My first question is, are ext_func missing some data on the float stack(ST), and is therefore not able to make the float value?(I understand you dont have the callee function, but doesnt matter what the function does?)
  • Second, does the compiler allways go to to the f-stack to get float values if it expects them, or is it possible to read them from the memorystack?
  • Third, is there seomething else I'm missing here? If I
printf("%f", a);     //3.140000  
printf("%f", str);      //3.140000

but the other way a gives big negativ number(100 digits or so) ended by 000000.


回答1:


The 32 bit convention uses the cpu stack to pass floating point arguments. It only uses the fpu stack for returning them. Yes, you should convert your 32 bit float to a 64 bit double, as per the prototypes you provided.

Note that ext_func is void, that is it doesn't return anything, but you declared tester as returning double ... it's unclear what you want returned, I will assume you want the original d back (for whatever reason).

As such, a possible implementation could be:

     .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


来源:https://stackoverflow.com/questions/30322006/call-function-with-float-in-assembly-x86-x87

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!