fldd386.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 392 行 · 第 1/2 页

ASM
392
字号
            ret                         ; - - return 0
          _endif                        ; - endif
          rcr   SI,1                    ; - put back the sign
        _endguess                       ; endguess

        push    EBP                     ; save EBP
        mov     EBP,ESP                 ; get access to stack
        push    EDI                     ; save EDI

        xchg    ECX,ESI         ; get exponents and signs into ECX
        mov     EDI,ECX         ; get exponent and sign of op1 into EDI
        rol     EDI,16          ; shift to top
        sar     EDI,16          ; shift exponent to bottom, duplicating sign
        sar     ECX,16          ; shift exponent to bottom, duplicating sign
        and     EDI,80007FFFh           ; isolate signs and exponent
        and     ECX,80007FFFh           ; ...
        rol     EDI,16                  ; rotate signs to bottom
        rol     ECX,16                  ; ...
        add     DI,CX                   ; calc sign of result
        rol     EDI,16                  ; rotate signs to top
        rol     ECX,16                  ; ...

        or      DI,DI                   ; if op1 is a denormal
        _if     e                       ; then
          _loop                         ; - loop (normalize it)
            _shl  EAX,1                 ; - - shift fraction left
            _rcl  EDX,1                 ; - - . . .
            dec   DI                    ; - - decrement exponent
            or    EDX,EDX               ; - - check for implied 1 bit
          _until  s                     ; - until implied 1 bit is on
        _endif                          ; endif
        or      CX,CX                   ; if op2 is a denormal
        _if     e                       ; then
          _loop                         ; - loop (normalize it)
            _shl  EBX,1                 ; - - shift fraction left
            _rcl  ESI,1                 ; - - . . .
            dec   CX                    ; - - decrement exponent
            or    ESI,ESI               ; - - check for implied 1 bit
          _until  s                     ; - until implied 1 bit is on
        _endif                          ; endif

        sub     DI,CX                   ; calculate exponent of result
        add     DI,3FFFh                ; add in removed bias
        _guess                          ; guess: overflow
          _quif s                       ; - quit if exponent is negative
          cmp   DI,7FFFh                ; - quit if not overflow
          _quif b                       ; - . . .
          mov   EDI,ECX                 ; - get sign
          mov   DI,7FFFh                ; - set infinity
          mov   EDX,80000000h           ; - ...
          sub   EAX,EAX                 ; - ...
          jmp   _divret                 ; - return (infinity)
        _endguess                       ; endguess
        cmp     DI,-64                  ; if exponent is too small
        _if     l                       ; then underflow
          sub   EAX,EAX                 ; - set result to 0
          sub   EDX,EDX                 ; - ...
          sub   EDI,EDI                 ; - ...
          jmp   _divret                 ; - return (underflow)
        _endif                          ; endif

        push    EDI                     ; save sign and exponent
        push    ESI                     ; save divisor
        push    EBX                     ; ...
        mov     ECX,ESI                 ; get top part of divisor
        mov     EDI,EDX                 ; get dividend
        mov     ESI,EAX                 ; ...
        sub     EAX,EAX                 ; assume top bit is 0
        cmp     ECX,EDI                 ; check high parts
        _if     be                      ; if hi(divisor) <= hi(dividend)
          sub   EDX,ECX                 ; - subtract divisor from dividend
          inc   EAX                     ; - set quotient to 1
        _endif                          ; endif
        push    EAX                     ; save high word of quotient
        mov     EAX,ESI                 ; get low part of dividend
        div     ECX                     ; estimate next word of quotient
        push    EAX                     ; save estimate of quotient (quot+4[EBP])
        xchg    EAX,EBX                 ; save quot., get low word of divisor
        mul     EBX                     ; calc. estimate * lo(divisor)
        xchg    EAX,ECX                 ; ...
        xchg    EBX,EDX                 ; save partial product
        mul     EDX                     ; calc. estimate * hi(divisor)
        add     EAX,EBX                 ; add to partial product
        adc     EDX,0                   ; ...
        mov     EBX,den+lo[EBP]         ; get low word of divisor
        test    byte ptr quot+8[EBP],1  ; if high word of quot is 1
        _if     ne                      ; then
          add   EAX,EBX                 ; - add in divisor
          adc   EDX,den+hi[EBP]         ; - ...
        _endif                          ; endif
; subtract estimate * divisor from dividend
        neg     ECX                     ; 0 - ECX
        sbb     ESI,EAX                 ; ...
        sbb     EDI,EDX                 ; ...
        _if     ne                      ; if high word not 0 (quotient too big)
          _loop                         ; - loop (find correct quotient)
            sub   dword ptr quot+4[EBP],1; - - decrement quotient
            sbb   dword ptr quot+8[EBP],0; - - ...
            add   ECX,EBX               ; - - add divisor back to dividend
            adc   ESI,den+hi[EBP]       ; - - ...
            adc   EDI,0                 ; - - ...
          _until  e                     ; - until done
        _endif                          ; endif
        mov     EDI,ESI                 ; get new dividend
        mov     ESI,ECX                 ; ...
        mov     ECX,den+hi[EBP]         ; get divisor
        cmp     ECX,EDI                 ; check high parts      13-aug-90
        _if     be                      ; if hi(divisor) <= hi(dividend)
          sub   EDI,ECX                 ; - subtract divisor from dividend
          add   dword ptr quot+4[EBP],1 ; - increment quotient
          adc   dword ptr quot+8[EBP],0 ; - ...
        _endif                          ; endif
        mov     EDX,EDI                 ; get dividend into EDX:EAX
        mov     EAX,ESI                 ; ...
        div     ECX                     ; estimate next word of quotient
        push    EAX                     ; save estimate of quotient (-4[EBP])
        or      EAX,EAX                 ; if quotient non-zero
        _if     ne                      ; then
          xchg  EAX,EBX                 ; - save quot., get low word of divisor
          mul   EBX                     ; - calc. estimate * lo(divisor)
          xchg  EAX,ECX                 ; - ...
          xchg  EBX,EDX                 ; - save partial product
          mul   EDX                     ; - calc. estimate * hi(divisor)
          add   EAX,EBX                 ; - add to partial product
          adc   EDX,0                   ; - ...
;   - subtract estimate * divisor from dividend
          neg   ECX                     ; - 0 - ECX
          sbb   ESI,EAX                 ; - ...
          sbb   EDI,EDX                 ; - ...
          _if   ne                      ; - if high word not 0 (quotient too big)
            _loop                       ; - - loop (find correct quotient)
              sub   dword ptr quot+0[EBP],1; - - - decrement quotient
              sbb   dword ptr quot+4[EBP],0; - - - ...
              sbb   dword ptr quot+8[EBP],0; - - - ...
              add   ECX,den+lo[EBP]     ; - - - add divisor back to dividend
              adc   ESI,den+hi[EBP]     ; - - - ...
              adc   EDI,0               ; - - - ...
            _until  e                   ; - - until done
          _endif                        ; - endif
        _endif                          ; endif
        pop     EAX                     ; get quotient
        pop     EDX                     ; ...
        pop     EBX                     ; get high bit
        add     ESP,8                   ; remove divisor
        pop     EDI                     ; restore sign and exponent
        dec     DI                      ; decrement exponent
        shr     EBX,1                   ; if non-zero
        _if     c                       ; then
          rcr   EDX,1                   ; - shift answer right
          rcr   EAX,1                   ; - ...
          inc   EDI                     ; - increment exponent
        _endif                          ; endif

;;      sub     ESI,ESI                 ; get zero for zero fill
;;
;;      _shl    ESI,1                   ; get guard bit
;;      adc     EAX,0                   ; round up
;;      adc     EDX,0                   ; ...
;;      adc     EDI,0                   ; increment exponent if required

        or      DI,DI                   ; if exponent <= 0
        _if   le                        ; then (denormal result)
          _if   e                       ; - if exponent = 0
            mov   CL,1                  ; - - set shift count to 1
          _else                         ; - else
            neg   DI                    ; - - negate to get shift count
            mov   CX,DI                 ; - - ...
          _endif                        ; - endif
          sub     EBX,EBX               ; - for zero fill
          shrd    EAX,EDX,CL            ; - align the fraction
          shrd    EDX,EBX,CL            ; - ...
          sub     DI,DI                 ; - set exponent to 0
        _endif                          ; endif
_divret:
        _shl    EDI,1                   ; get sign
        rcr     DI,1                    ; merge it with exponent
        mov     ESI,EDI                 ; get exponent and sign into SI
        pop     EDI                     ; ...
        pop     EBP                     ; ...
        ret                             ; return

        endproc ___LDD


ifdef _BUILDING_MATHLIB

        endmod

        endf    equ end
else
        endf    equ <>

endif

endf

⌨️ 快捷键说明

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