fpuexam.asm

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

ASM
143
字号
; #########################################################################
;
;                             FpuExam
;
;##########################################################################

  ; -----------------------------------------------------------------------
  ; This procedure was written by Raymond Filiatreault, December 2002
  ;
  ; This FpuExam function examines an 80-bit REAL number (Src) for its
  ; validity, its sign, a value of zero, an absolute value less than 1, and
  ; a value of infinity.
  ; The result is returned in EAX as coded bits:
  ;         EAX = 0     invalid number
  ;         bit 0       1 = valid number
  ;         bit 1       1 = number is equal to zero
  ;         bit 2       1 = number is negative
  ;         bit 3       1 = number less than 1 but not zero
  ;         bit 4       1 = number is infinity
  ; If the source was on the FPU, it will be preserved if no error is
  ; reported.
  ;
  ; The source can only be an 80-bit REAL number from the FPU itself or
  ; from memory.
  ;
  ; Only EAX is used to return error or the result of the examination. All
  ; other registers are preserved.
  ;
  ; -----------------------------------------------------------------------

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

    include Fpu.inc

    .data

    stflags dd    0
    stword  dw    0

    .code

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

FpuExam proc public lpSrc: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.

      mov   stflags,0         ;initialize flags
      fclex                   ;clear exception flags on FPU
      test  uID,SRC1_FPU      ;is Src taken from FPU?
      jnz   dest0             ;go complete process
      finit
      
;----------------------------------------
;check source for Src and load it to FPU
;----------------------------------------

      test  uID,SRC1_REAL     ;is Src an 80-bit REAL in memory?
      jz    srcerr            ;no proper source identificaiton
      mov   eax,lpSrc
      fld   tbyte ptr [eax]
      jmp   dest0             ;go complete process

srcerr:
      finit
      xor   eax,eax
      ret

dest0:
      ftst                    ;test number
      fstsw stword            ;retrieve exception flags from FPU
      fwait
      test  stword,1          ;invalid operation?
      jnz   srcerr

      test  stword,4000h      ;0 value or NAN?
      jz    @F
      test  stword,100h       ;NAN or infinity
      jnz   examine           ;go check for infinity value
      or    stflags,XAM_ZERO
      jmp   finish            ;no need for checking for sign or size if 0
      
   @@:
      test  stword,100h       ;is number negative?
      jz    @F
      or    stflags,XAM_NEG

;check for size smaller than 1 by taking the logarithm of the absolute value
; and checking if it is negative

   @@:
      fld   st(0)             ;copy the number to get its logarithm
      fabs                    ;make sure it is positive
      fld1                    ;for multiplying by 1
      fxch                    ;for next instruction
      fyl2x                   ;gets the logarithm * 1
      ftst                    ;test number
      fstsw stword            ;retrieve status word from FPU
      fstp  st(0)             ;get rid of the tested value
      test  stword,4000h      ;0 or infinity?
      jnz   finish            ;if the logarithm is 0, the value was = 1
      test  stword,100h       ;is logarithm negative?
      jz    finish
      or    stflags,XAM_SMALL ;values less than 1 have a negative logarithm

finish:
      test  uID,SRC1_FPU      ;check what was source
      jnz   @F                ;leave result on FPU if it was the source
      finit
@@:
      mov   eax,stflags
      or    al,1              ;to indicate source was a valid number
      ret

examine:                      ;strictly for infinity value
      fxam
      fstsw stword            ;retrieve result of fxam
      fwait
      mov   ax,stword
      and   ah,45h            ;mask C0,C2, and C3
      cmp   ah,5              ;test for infinity
      jnz   srcerr            ;must be NAN
      or    stflags,XAM_INFINIT
      jmp   finish
      

FpuExam endp

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

end

⌨️ 快捷键说明

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