Page 1 of 1

cdecl and floating points

Posted: Mon Mar 22, 2010 3:58 pm
by ~
The 32-bit cdecl calling convention says that the primitive data types, except for floating point values, are returned in EAX or EDX:EAX, depending on its size. EBX, ESI, EDI and EBP are preserved. EAX, ECX and EDX can be destroyed and aren't preserved. ESP and EBP are used for stack access, specially EBP which will hold the original base address of parameters in the stack, and ESP can be modified to create a stack frame, as an example here:

http://en.wikibooks.org/wiki/X86_Disass ... ack_Frames

Everything seems to be well until there. It seems that a cdecl function could be coded like this:

Code: Select all

some_function:
 push ebp        ;save EBP
 mov ebp,esp     ;point EBP to current stack position
 add ebp,8       ;discard, in EBP, the saved EBP size to point directly to parameters
                 ;and also the return addres that was pushed by near CALL instruction
   push ebx
   push esi
   push edi


   pop edi
   pop esi
   pop ebx
 pop ebp
ret

Now, what seems strange are the floating point values and how to handle them, which are said to be returned as a single return value in FP0 register of the FPU. First of all there doesn't seem to be a convention to save anything from the FPU state. Is this supposition correct?

The other problem is, how can a program using floating point values run in a machine without FPU, like a 386DX. How can a "float" type routine return value and "float" arguments in stack be handled at compile time?

Re: cdecl and floating points

Posted: Mon Mar 22, 2010 4:39 pm
by Combuster
What it says is that upon entry, the FPU stack must be empty, and on return, the stack may at most contain one item - the return value, if it is a floating point number.

In ancient times there were three ways of dealing with floats:
1: don't use them; use fixed point or software floats.
2: use them, and blame the user's hardware if it stops working
3: use them, but emulate them when necessary (via the EM exception)

in case #1, there's no float to pass on-stack. In case #2 you'd want to pass as efficiently as possible - i.e. leave them on the stack to avoid a 4x bus sized read and 4x bus sized write - doubles over a 16 bit bus is not smart.
In case #3, you back up the corner case, such that when you do access the FPU, the result gets emulated, and you can still pass it "on the stack" (in that case, a virtual one), which is again more efficient than adding another pair of exceptions and memory writes for storing the result which will get used directly after...

Re: cdecl and floating points

Posted: Wed Mar 24, 2010 1:14 pm
by Craze Frog
First of all there doesn't seem to be a convention to save anything from the FPU state. Is this supposition correct?
You must preserve fpu state like rounding mode, unless the whole point of the called function IS to change the fpu state.