Hullo, I am learning x86 FPU assembly, and I have got a simple question I cannot find answer for:
How to move value from ST(0)
( top of the FPU
stack ) to EAX
?
also:
is this code correct:
; multiply (dot) two vectors of 3 floats passed by pointers as arg 1 arg 2
; passings are ok I think, but not sure if multiplies-adds are ok
push ebp
mov ebp, esp
mov eax, dword [ebp+8H]
mov edx, dword [ebp+0CH]
fld qword [eax]
fmul qword [edx]
fld qword [eax+4H]
fmul qword [edx+4H]
fld qword [eax+8H]
fmul qword [edx+8H]
faddp st1, st(0)
faddp st1, st(0)
fstp qword [ebp+10H] ; here I vould prefer 'mov eax, st0'
pop ebp
ret
There is no real reason why you should. Remember that EAX
is only a 32-bit register, while all the FPU registers are 80 bits in width, because the FPU does calculations on 80-bit floats by default. Therefore, moving data from the FPU register to a general purpose register will cause data loss. If you really want to do something like that, try this (assuming that you've got some stack space available) :
sub esp, 4 ; or use space you already reserved
fstp dword [esp]
mov eax, [esp] ; or better, pop eax
add esp, 4
This instruction sequence will round the float currently on the top of the FPU stack to a 32-bit one, then write it to a temporary stack location, load the float
(binary32) bit pattern into EAX
, and clean up the used stack space.
This is almost never what you want. The standard calling conventions return float / double / long double values in st(0)
, so that's where a C compiler will expect a double foo()
function to leave the value. (Or xmm0
with SSE/SSE2).
You only need this if you want to do integer manipulation / tests on FP bit-patterns. (i.e. to implement type-punning in C like memcpy
from a float
to uint32_t
). e.g. for the famous but now mostly obsolete fast approximate inverse-sqrtf
magic-number hack used in Quake source code.