fpusize.asm

来自「工欲善其事」· 汇编 代码 · 共 153 行

ASM
153
字号
; #########################################################################
;
;                             FpuSize
;
;##########################################################################

  ; -----------------------------------------------------------------------
  ; This procedure was written by Raymond Filiatreault, December 2002
  ;
  ; 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 there if considered valid. The
  ; destination must be a pointer to a LONG integer.
  ;
  ; 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, adjusted
  ; if necessary for a negative value.
  ;
  ; Only EAX is used to return error or success. All other registers are
  ; preserved.
  ;
  ; -----------------------------------------------------------------------

    .486
    .model flat, stdcall  ; 32 bit memory model
    option casemap :none  ; case sensitive

    include Fpu.inc

    .data

    tempdw  dd    0
    stword  dw    0
    oldcw   dw    0

    .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.
;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

; the FPU will be initialized only if the source parameter is not taken
; from the FPU itself.

      fclex                   ;clear exception flags on FPU
      test  uID,SRC1_FPU      ;is Src taken from FPU?
      jz    @F
      fld   st(0)             ;copy it to preserve the original value
      jmp   dest0             ;go complete process
@@:
      finit
      
;----------------------------------------
;check source for Src and load it to FPU
;----------------------------------------

      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
      mov   tempdw,eax
      fild  tempdw
      jmp   dest0             ;go complete process
      
srcerr:
      finit
      xor   eax,eax
      ret

dest0:
      fabs                    ;insures a positive value
      ftst                    ;check the value on the FPU
      fstsw stword            ;store the result
      fwait
      test  stword,4000h      ;test it for NAN or zero value
      jz    @F                ;not NAN or zero
      test  stword,100h       ;test for NAN
      jnz   srcerr            ;invalid number or infinity
      mov   eax,80000000h     ;code it for 0 value
      jmp   finish            ;this avoids an invalid operation if computing
                              ;the logarithm of zero was attempted

   @@:
      fld1
      fldl2t                  ;load log2(10)
      fdiv                    ;->1/[log2(10)]
      fxch                    ;set up registers for next operation
      fyl2x                   ;->[log2(x)]/[log2(10)] = log(x) base 10
      
      fstcw oldcw             ;get current control word
      fwait
      mov   ax,oldcw
      or    ax,0c00h          ;code it for truncating
      mov   stword,ax
      fldcw stword            ;change rounding code of FPU to truncate
      
      fist  tempdw            ;store integer result at temporary address
      fldcw oldcw             ;load back the former control word

      mov   eax,tempdw
      ftst                    ;test logarithm for its sign
      fstsw stword            ;get result
      fwait
      test  stword,100h       ;check it negative
      jz    @F
      dec   eax               ;for scientific notation, the mantissa of a
                              ;logarithm must always be positive. If negative
                              ;its characteristic needs to be decremented.
   @@:
      fstp  st(0)             ;get rid of the logarithm

finish:
      push  ebx
      mov   ebx,lpDest
      mov   [ebx],eax
      pop   ebx

      or    al,1              ;to insure EAX!=0
      ret
    
FpuSize endp

; #########################################################################

end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?