div386.asm

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

ASM
308
字号
          pop   ESI                     ; - restore ESI
          pop   EDI                     ; - restore EDI
          pop   EBP                     ; - restore EBP
          jmp   F8OverFlow              ; - handle overflow
        _endguess                       ; endguess
        cmp     DI,-52                  ; if exponent is too small
        _if     l                       ; then underflow
          pop   ESI                     ; - restore ESI
          pop   EDI                     ; - restore EDI
          pop   EBP                     ; - restore EBP
          jmp   F8UnderFlow             ; - handle underflow
        _endif                          ; endif

        push    EDI                     ; save sign and exponent
        mov     CL,11                   ; shift fractions to top of registers
        shld    EDX,EAX,CL              ; ...
        shld    EAX,EBP,CL              ; ...
        and     EAX,0FFFFF800h          ; ...
        shld    ESI,EBX,CL              ; ...
        shld    EBX,EBP,CL              ; ...
        and     EBX,0FFFFF800h          ; ...
        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,EDX                 ; 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
        mov     CL,11                   ; shift result over
        shrd    EAX,EDX,CL              ; ...
        rcr     ESI,1                   ; save carry
        shrd    EDX,ESI,CL              ; ...

        or      EDX,0FFF00000h          ; turn top bits all on
        _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
          and     EDX,001FFFFFh         ; - isolate fraction
          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

        and     EDX,000FFFFFh           ; isolate fraction
        mov     ESI,EDI                 ; get copy of sign
        ror     EDI,11                  ; get exponent
        _shl    ESI,1                   ; get sign
        rcr     EDI,1                   ; put it in
        and     EDI,0FFF00000h          ; isolate sign and exponent
        or      EDX,EDI                 ; place it in result

        pop     ESI                     ; restore registers
        pop     EDI                     ; ...
        pop     EBP                     ; ...
        ret                             ; return
        endproc __FDD

        endmod
        end

⌨️ 快捷键说明

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