📄 fpusize.asm
字号:
; #########################################################################
;
; FpuSize
;
;##########################################################################
; -----------------------------------------------------------------------
; This procedure was written by Raymond Filiatreault, December 2002.
; Modified March 2004 to avoid any potential data loss from the FPU
;
; This FpuSize function computes the exponent of a number (Src) as if it
; were expressed in scientific notation and returns the result as a LONG
; integer at the specified destination, unless an invalid operation
; is reported by the FPU or the definition of the parameters (with uID)
; is invalid.
;
; The source can be an 80-bit REAL number from the FPU itself or from
; memory, or an immediate DWORD value or one in memory. The FPU
; constants are not allowed as input. If the source is taken from the
; FPU, its value will be preserved. The destination must be a pointer
; to a 32-bit integer memory variable.
;
; The source is not checked for validity. This is the programmer's
; responsibility.
;
; This function simply computes the common logarithm (base 10) of the
; absolute value of the number and returns the characteristic
; (i.e. power of 10), adjusted if necessary for a negative log value.
; For example,
; 5432 would return +3 (log = 3.735)
; 5.432 would return 0 (log = 0.735)
; 0.05432 would return -2 (log = -1.265)
;
; Only EAX is used to return error or success. All other CPU registers
; are preserved. All FPU registers are preserved.
;
; -----------------------------------------------------------------------
.386
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include Fpu.inc
.code
; #########################################################################
FpuSize proc public lpSrc:DWORD, lpDest:DWORD, uID:DWORD
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;
; Because a library is assembled before its functions are called, all
; references to external memory data must be qualified for the expected
; size of that data so that the proper code is generated.
;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LOCAL content[108] :BYTE
LOCAL tempst :TBYTE
test uID,SRC1_FPU ;is Src taken from FPU?
jz continue ;go check for potential overflow
;-------------------------------
;check if top register is empty
;-------------------------------
fxam ;examine its content
fstsw ax ;store results in AX
fwait ;for precaution
sahf ;transfer result bits to CPU flag
jnc continue ;not empty if Carry flag not set
jpe continue ;not empty if Parity flag set
jz srcerr1 ;empty if Zero flag set
continue:
fsave content
;----------------------------------------
;check source for Src and load it to FPU
;----------------------------------------
test uID,SRC1_FPU ;is Src taken from FPU?
jz @F
lea eax,content
fld tbyte ptr[eax+28]
jmp dest0 ;go complete process
@@:
mov eax,lpSrc
test uID,SRC1_REAL ;is Src an 80-bit REAL in memory?
jz @F
fld tbyte ptr [eax]
jmp dest0 ;go complete process
@@:
test uID,SRC1_DMEM ;is Src a 32-bit integer in memory?
jz @F
fild dword ptr [eax]
jmp dest0 ;go complete process
@@:
test uID,SRC1_DIMM ;is Src an immediate 32-bit integer?
jz srcerr ;no correct flag for Src
fild lpSrc
jmp dest0 ;go complete process
srcerr:
frstor content
srcerr1:
xor eax,eax
ret
dest0:
fabs ;insures a positive value
ftst ;check the value on the FPU
fstsw ax ;store the result flags in AX
fwait
sahf ;transfer flags to CPU flag register
jnz @F ;not NAN or zero
jc srcerr ;invalid number or infinity
mov eax,lpDest
mov dword ptr[eax],80000000h ;code it for 0 value
jmp finish ;this avoids an invalid operation if computing
;the logarithm of zero was attempted
@@:
fldlg2 ;load log10(2)
fxch ;set up registers for next operation
fyl2x ;->[log2(x)]*[log10(2)] = log(x) base 10
push eax ;reserve space on CPU stack
fstcw [esp] ;get current control word
fwait
mov ax,[esp]
and ax,0f3ffh ;clear RC field
or ax,0400h ;code it for rounding down
push eax
fldcw [esp] ;change rounding code of FPU to rounding down
;towards -INFINITY
mov eax,lpDest
fistp dword ptr[eax] ;store integer result at specified address
fldcw [esp+4] ;load back the former control word
add esp,8 ;restore stack pointer
finish:
frstor content
or al,1 ;to insure EAX!=0
ret
FpuSize endp
; #########################################################################
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -