Well I don?t think I am good with FPU instructions so I am asking you guys to, please, give me comments and your opinions about the below procedure. It converts an angle expressed in Degrees to an angle expressed in Cycles. I am using Double Precision Floating Point values here but I really do not know if what I am doing is an optimal way of calculating this value.


; --------------------------------------------------
%DEFINE    TBYTE    TWORD
; --------------------------------------------------
  __MathDegToCycle:
    ; void __MathDegToCycle (const TBYTE* DegAngle, TBYTE* Result); StdCall;
    ; Deg To Cycle = (Deg * PI/180) / (2 * PI)
    PUSH    EAX                                ; Push the accumulator onto the stack
    PUSH    EBP                                ; Push the base pointer onto the stack
    MOV    EBP , ESP                          ; Move the stack pointer to the base pointer
    SUB    ESP , 0x0000000A                    ; Allocate 10 bytes of the stack space for immediate float values
    LEA    EAX ,                   ; *EAX = The allocated space in the stack
    MOV    DWORD PTR , 0x94E9C8AE        ; DWORD #0 of Extended Precision Floating Point value of (PI/180)
    MOV    DWORD PTR , 0x8EFA3512 ; DWORD #1 of Extended Precision Floating Point value of (PI/180)
    MOV    WORD  PTR , 0x3FF9    ; Last WORD of Extended Precision Floating Point value of (PI/180)
    FLD    TBYTE PTR                     ; ST0 = PI/180 (Deg To Cycle = (Deg * (PI/180)) / (2 * PI))
    FWAIT                                      ; Wait for the value to be loaded
    MOV    EAX , DWORD PTR         ; *EAX = Points to the parameter
    FLD    TBYTE PTR                     ; ST0 = , ST1 = PI/180
    FWAIT                                      ; Wait for the value of to be loaded into the FPU
    FMULP  ST1 , ST0                          ; ST0 = * (PI/180) , ST1 = Free
    FWAIT                                      ; Wait for the calculation to be completed by the FPU
    LEA    EAX ,                   ; *EAX = Pointer to the stack allocated space
    MOV    DWORD PTR , 0x2168C235        ; DWORD #0 of Extended Precision Floating Point value of (2 * PI)
    MOV    DWORD PTR , 0xC90FDAA2 ; DWORD #1 of Extended Precision Floating Point value of (2 * PI)
    MOV    WORD  PTR , 0x4001    ; Last WORD of Extended Precision Floating Point value of (2 * PI)
    FLD    TBYTE PTR                     ; ST0 = 2*PI, ST1 = * (PI/180)
    FWAIT                                      ; Wait for the value to be loaded into the FPU
    FDIVP  ST1 , ST0                          ; ST0 = ( * (PI/180)) / (2 * PI) = DegAngle -> CyclesAngle
    FWAIT                                      ; Wait for the computation to complete in the FPU
    MOV    EAX , DWORD PTR         ; *EAX = Pointer to the parameter
    FSTP    TBYTE PTR                     ; Store the result in the parameter; ST0 = Free
    ADD    ESP , 0x0000000A                    ; Deallocate 10 bytes of the stack space
    POP    EBP                                ; Restore the base pointer
    POP    EAX                                ; Restore the accumulator
    RET    0x08                                ; Return to the calling procedure
                                                ; And sweep 2 parameter off the stack
Posted on 2007-03-26 05:00:30 by XCHG

MathDegToCycle proc uses eax pDegree:ptr real8,pResult:ptr real8
mov eax,pDegree
.data
fOneOver360 QWORD 3F66C16C16C16C17h ; = 1/360, maximum precision
.code
fld real8 ptr
mov eax,pResult
fmul fOneOver360
fstp real8 ptr

ret
MathDegToCycle endp
Posted on 2007-03-26 05:48:00 by Ultrano
Ultrano,

That was one hell of a solution. Thank you so much but I don't seem to be able to get the difference between extended precision and doubles. Which one is which? Where am I? Who are you?
Posted on 2007-03-26 09:37:57 by XCHG
That 8-byte value - I got it directly with

.data
temp real4 360.0
.code
fld1
fdiv temp
fstp fOneOver360 ; the variable is actually a "real8"

Otherwise, if you simply put such a value as 0.0027777777777777777777777777, the assembler might lose a bit of precision.

Probably you'll need to change "real8" to TBYTE  (real10) from the code I posted. Some FPU instructions can't handle real10 data, so I never use real10.
Posted on 2007-03-26 10:25:36 by Ultrano
in C/C++,
float: 4 bytes
double : 8 bytes
long double : 10 bytes

in asm
real4 / dd / DWORD
real8 / dq / QWORD
real10/ dt / TBYTE
Posted on 2007-03-26 10:38:41 by Ultrano
Just checked MSDN 2005, and... in VS2k5 "long double" is 8 bytes instead of 10. (and there's no alternative for 10-byte floats) Perhaps it's done in order to simplify the compiler's optimization routines.
Posted on 2007-03-26 10:47:07 by Ultrano

in C/C++,
float: 4 bytes
double : 8 bytes
long double : 10 bytes

not true. Types in C are not quaranteed to have any size (some have quaranteed minimal size). All you know is that  sizeof(long double) >= sizeof(double) >= sizeof(float).

You should define your own types when you need data of exact size
Posted on 2007-03-26 12:24:49 by vid
Afaik Microsoft dropped REAL10 support quite a while ago... probably as long ago as VC6.
Posted on 2007-03-26 17:10:10 by f0dder