News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

returning floats

Started by d0d0, February 01, 2009, 04:21:48 PM

Previous topic - Next topic

d0d0

howdy folks,

need some advice on returning floats from my assembly routines.

should i return in st0 or return via a param to the routine.

c lang e.g.

float Vec3_Dot(Vec3 v1, Vec3 v2) or

void Vec3_Dot(Vec3 v1, Vec3 v2, float *ret)

what about for sse routines?

thanks.

jj2007

There are no established rules afaik. Be consistent...
One convenient way is to pass a pointer to a REAL8, and to pop the result from ST0 to this variable.

lea edx, MyLocR8
fstp REAL8 ptr [edx]

MichaelW

AFAIK C compilers normally pass floats on the stack and return floats in ST(0). And since your code will need to do it this way if it passes/returns/receives a float to/from a C or CRT function, I think this is a reasonable convention to adopt for asm procedures. Invoke can pass floats (REAL4, REAL8, or REAL10) on the stack, and you can access them within a procedure, without having to do anything unusual. And returning in ST(0) has the non-obvious advantage that the return value can be stored as any type that the FPU supports.
eschew obfuscation

d0d0

mucho gracias me amigos :bg

respect!

raymond

Just a reminder. Beware of calling some of the Windows APIs (such as MessageBox) while you are retaining data in FPU registers. That data may get trashed.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

d0d0

thanks.

raymond, do you have any advice you could share on creating vector math libraries? I've started on a little small project to create a numerical library. I intend to expand it as I progress through my math course and improve on asm.

thanks.

jj2007

Quote from: raymond on February 02, 2009, 02:27:03 AM
Just a reminder. Beware of calling some of the Windows APIs (such as MessageBox) while you are retaining data in FPU registers. That data may get trashed.


Indeed. One (rather weak, I know) argument to pass a pointer to a real8 rather than returning the value on the FPU.
Attached a test proggie. On Win XP SP2, it seems that ST0-ST2 are OK but the rest gets trashed.

I could understand this behaviour if message boxes were typically found in innermost speed-critical loops. Greetings to the developers of BloatOS... :green

start: push eax ; create a stack slot
mov dword ptr [esp], 100007
fild dword ptr [esp]
mov dword ptr [esp], 100006
fild dword ptr [esp]
mov dword ptr [esp], 100005
fild dword ptr [esp]
mov dword ptr [esp], 100004
fild dword ptr [esp]
mov dword ptr [esp], 100003
fild dword ptr [esp]
mov dword ptr [esp], 100002
fild dword ptr [esp]
mov dword ptr [esp], 100001
fild dword ptr [esp]
mov dword ptr [esp], 100000
fild dword ptr [esp]
pop eax ; release stack slot
deb 1, "TestBox 1:", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)
deb 1, "TestBox 2:", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)

[attachment deleted by admin]

d0d0

why would a call to an api function for a msg box trash the fpu registers!

what about on linux?

d0d0

Quote from: jj2007 on February 02, 2009, 02:48:38 PM
Quote from: raymond on February 02, 2009, 02:27:03 AM
Just a reminder. Beware of calling some of the Windows APIs (such as MessageBox) while you are retaining data in FPU registers. That data may get trashed.


Indeed. One (rather weak, I know) argument to pass a pointer to a real8 rather than returning the value on the FPU.
Attached a test proggie. On Win XP SP2, it seems that ST0-ST2 are OK but the rest gets trashed.

I could understand this behaviour if message boxes were typically found in innermost speed-critical loops. Greetings to the developers of BloatOS... :green

start: push eax ; create a stack slot
mov dword ptr [esp], 100007
fild dword ptr [esp]
mov dword ptr [esp], 100006
fild dword ptr [esp]
mov dword ptr [esp], 100005
fild dword ptr [esp]
mov dword ptr [esp], 100004
fild dword ptr [esp]
mov dword ptr [esp], 100003
fild dword ptr [esp]
mov dword ptr [esp], 100002
fild dword ptr [esp]
mov dword ptr [esp], 100001
fild dword ptr [esp]
mov dword ptr [esp], 100000
fild dword ptr [esp]
pop eax ; release stack slot
deb 1, "TestBox 1:", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)
deb 1, "TestBox 2:", ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7)


lol. they all get trashed on vista (server 2008)! :lol

donkey

The Windows ABI covers this, in Win32 floats are return in ST0

QuoteVisual C++ / Win32

   * Arguments are pushed on the stack in reverse order.
   * The callee pops arguments when returning.
   * Primitive data types, except floating point values, are returned in EAX or EAX:EDX depending on the size.
   * float and double are returned in ST0, i.e. the first floating point register.
   * Simple data structures with 8 bytes or less in size are returned in EAX:EDX.
   * Class objects that require special treatment by the exception handler are returned in memory. Classes with a defined constructor, destructor, or overloaded assignment operator are examples of these.
   * Objects larger than 8 bytes are returned in memory.
   * When a return is made in memory the caller passes a pointer to the memory location as the first parameter (hidden). The callee populates the memory, and returns the pointer. The callee pops the hidden pointer together with the rest of the arguments

In x64 they are returned in XMM0

QuoteMost return values that can fit into 64 bits (including __m64 types) are returned through the RAX register. However, the types __m128, __m128i, __m128d, floats, and doubles are returned in the XMM0 register. If the return value does not fit within 64 bits, then the caller must allocate and pass a pointer for the return value as the first argument. Subsequent arguments are then shifted one argument to the right. User-defined types to be returned must be 1, 2, 4, 8, 16, 32, or 64 bits in length.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: d0d0 on February 02, 2009, 03:46:32 PM
lol. they all get trashed on vista (server 2008)! :lol

I am afraid it's worse than that, i.e. you cannot rely on this behaviour: On XP SP2, ST0-2 get often trashed - in a non-predictable way (and there are no API calls between the first and second MessageBox).

raymond

Quotewhy would a call to an api function for a msg box trash the fpu registers!

After Win98, and sometime before WinXP, the MS programmers fell in love with the MMX set of instructions. It thus became standard practice to perform ALL calculations (even 2+2 I think) using MMX instructions. Those are processed with the FPU hardware.

Thus displaying a message box, for example, requires calculations to set its size and location. That's how and why the FPU registers get trashed by some API functions.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

d0d0

mmm....interesting. thanks. what about the other question? :bg

raymond

I have absolutely no knowledge about Linux. Someone else running with a Linux OS may be able to check it and eventually answer your question. It should be enlightening. I am also curious.

Anybody with a Linux box?????????? :clap: :clap: :clap:
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com