| ||
When a floating-point value becomes invalid due to overflows, etc., the easiest way to make it valid is stretch the value into a larger floating- point form, which becomes valid, and then store it back out as a valid form. Confusing?
The following is a code snippet that detects single-precision floating-point overflows. In this case, the value is radians.
OFLOW_FIXUP fRads ; Overflow fixup
OFLOW_FIXUP MACRO arg1 mov eax,DWORD PTR arg1 ; 03F800000h = 1.0f 0BF800000h=1.0 and eax,07F800000h cmp eax,07F800000h ;Check for an non-zero exponent! jne $ok mov eax,DWORD PTR arg1 call FixupReal4 $ok: ; ST(0)= value endm
To fix the overflow of a single-precision floating-point value, it can be expanded to double extended-precision floating-point or double-precision floating-point, such as in the following code snippet.
; Fixup Real4 (float) ; eax=bad float ; NOTE: ST(0) already contains the float!!! FixupReal4 proc near fstp qword ptr [esp810] ; Save Real8 (double) & pop ST(0) ; Build a Real10 mov eax,[esp810+4] ; Hi or eax,7FFF0000h ; Set Real8 (Double) mov dword ptr [esp10+6],eax ; 7FFFXXXX???????????? mov eax,[esp810+4] ; Real8 Hi mov ecx,[esp810+0] ; Real8 Lo shld eax,ecx,11 shl ecx,11 mov dword ptr [esp10+4],eax ; 7FFFHHHHHHHH???????? mov dword ptr [esp10+0],ecx ; FFFHHHHHHHHLLLLLLLL fld tbyte ptr [esp10+0] ; Load Real10 ret ; ST(0)=value FixupReal4 endp