fldd086.asm

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

ASM
502
字号
        div     SI              ; estimate next word of quotient
        push    AX              ; save estimate of quotient     (quot+4[BP])
        mov     SI,AX           ; get estimate as multiplier
;
;       calculate divisor * estimated quotient
;
        sub     CX,CX           ; zero CX
        mov     AX,den+0[BP]    ; get low order word of divisor
        mul     SI              ; do multiply
        mov     DI,AX           ; save result
        mov     BX,DX           ; ...
        mov     AX,den+2[BP]    ; get next word of divisor
        mul     SI              ; do multiply
        add     BX,AX           ; accumulate result
        adc     CX,DX           ; ...
        mov     AX,den+4[BP]    ; get next word of divisor
        mul     SI              ; do multiply
        add     CX,AX           ; accumulate result
        adc     DX,0            ; ...
        xchg    DX,SI           ; answer in SI, multiplier in DX
        mov     AX,den+6[BP]    ; get last word of divisor
        mul     DX              ; do multiply
        add     AX,SI           ; accumulate result
        adc     DX,0            ; ...

;       result is in DX:AX:CX:BX:DI

        cmp     word ptr quot+6[BP],0 ; if high word of quotient is 1
        _if     ne              ; then
          add   BX,den+0[BP]    ; - add in divisor
          adc   CX,den+2[BP]    ; - ...
          adc   AX,den+4[BP]    ; - ...
          adc   DX,den+6[BP]    ; - ...
        _endif                  ; endif
;
;       subtract estimate * divisor from dividend
;
        not     DX              ; negate estimate * divisor
        not     AX              ; ...
        not     CX              ; ...
        not     BX              ; ...
        neg     DI              ; ...
        sbb     BX,-1           ; ...
        sbb     CX,-1           ; ...
        sbb     AX,-1           ; ...
        sbb     DX,-1           ; ...
;
;       add dividend to this
;
        add     BX,num+0[BP]    ; ...
        adc     CX,num+2[BP]    ; ...
        adc     AX,num+4[BP]    ; ...
        adc     DX,num+6[BP]    ; ...
        _if     ne              ; if high word not 0 (quotient is too big)
          _loop                 ; - loop (find correct quotient)
            sub   word ptr quot+4[BP],1 ; - - decrement quotient
            sbb   word ptr quot+6[BP],0 ; - - ...
            add   DI,den+0[BP]  ; - - add divisor back to dividend
            adc   BX,den+2[BP]  ; - - ...
            adc   CX,den+4[BP]  ; - - ...
            adc   AX,den+6[BP]  ; - - ...
            adc   DX,0          ; - - ...
          _until  e             ; - until done
        _endif                  ; endif
        mov     num+0[BP],DI    ; save new dividend
        mov     num+2[BP],BX    ; ...
        mov     num+4[BP],CX    ; ...
        mov     num+6[BP],AX    ; ...

divloop:;_loop                  ; loop (for rest of estimates)


        xchg    DX,AX           ; get high part of dividend into DX:AX
        xchg    AX,CX           ; ...
        mov     SI,den+6[BP]    ; get high word of divisor
        cmp     SI,DX           ; if divisor <= high word of dividend
        _if     be              ; then
;         sub   DX,SI           ; - subtract divisor from dividend
;         pop   BX              ; - restore last word of quotient
;         add   BX,1            ; - increment it
;         _if   c               ; - if carry
;           pop   CX            ; - - get next word
;           add   CX,1          ; - - increment it
;         what about carry?
;           push  CX            ; - - save updated quotient word
;         _endif                ; - endif
;         push  BX              ; - restore last word of quotient
          mov   AX,0FFFFh       ; - set estimate to 0xffff
        _else                   ; else
          div   SI              ; - estimate next word of quotient
        _endif                  ; endif
        push    AX              ; save estimate of quotient     (quot+2[BP])
        sub     CX,CX           ; assume quotient is 0
        mov     BX,CX           ; ...
        mov     DX,AX           ; ...
        or      AX,AX           ; if quotient not zero
        _if     ne              ; then
          xchg  SI,AX           ; - get estimate as multiplier
;
;         calculate divisor * estimated quotient
;
          mov   AX,den+0[BP]    ; - get low order word of divisor
          mul   SI              ; - do multiply
          mov   DI,AX           ; - save result
          mov   BX,DX           ; - ...
          mov   AX,den+2[BP]    ; - get next word of divisor
          mul   SI              ; - do multiply
          add   BX,AX           ; - accumulate result
          adc   CX,DX           ; - ...
          mov   AX,den+4[BP]    ; - get next word of divisor
          mul   SI              ; - do multiply
          add   CX,AX           ; - accumulate result
          adc   DX,0            ; - ...
          xchg  DX,SI           ; - answer in SI, multiplier in DX
          mov   AX,den+6[BP]    ; - get last word of divisor
          mul   DX              ; - do multiply
          add   AX,SI           ; - accumulate result
          adc   DX,0            ; - ...

;       result is in DX:AX:CX:BX:DI
;
;       subtract estimate * divisor from dividend
;
          not   DX              ; - negate estimate * divisor
          not   AX              ; - ...
          not   CX              ; - ...
          not   BX              ; - ...
          neg   DI              ; - ...
          sbb   BX,-1           ; - ...
          sbb   CX,-1           ; - ...
          sbb   AX,-1           ; - ...
          sbb   DX,-1           ; - ...
;
;       add dividend to this
;
        _endif                  ; endif
        add     BX,num+0[BP]    ; ...
        adc     CX,num+2[BP]    ; ...
        adc     AX,num+4[BP]    ; ...
        adc     DX,num+6[BP]    ; ...
        _if     ne              ; if high word not 0 (quotient is too big)
          sub   SI,SI           ; - zero correction factor
          _loop                 ; - loop (find correct quotient)
            inc   SI            ; - - increment adjustment
            add   DI,den+0[BP]  ; - - add divisor back to dividend
            adc   BX,den+2[BP]  ; - - ...
            adc   CX,den+4[BP]  ; - - ...
            adc   AX,den+6[BP]  ; - - ...
            adc   DX,0          ; - - ...
          _until  e             ; - until done
          mov   DX,BP           ; - save BP
          mov   BP,SP           ; - get access to quotient
          sub   [BP],SI         ; - adjust quotient
;         _loop                 ; - loop
;           _quif  nc           ; - - quit if no borrow
;           add    BP,2         ; - - point to next word of quotient
;           sub word ptr [BP],1 ; - - adjust quotient
;         _endloop              ; - endloop
          mov   BP,DX           ; - restore DX
          sub   DX,DX           ; - zero DX
        _endif                  ; endif
        mov     num+0[BP],DI    ; save new dividend
        mov     num+2[BP],BX    ; ...
        mov     num+4[BP],CX    ; ...
        mov     num+6[BP],AX    ; ...

        dec   word ptr count[BP]; - decrement loop count
        _if     ne              ; if not done
          jmp   divloop         ; - continue
        _endif                  ; endif
;       _until  e               ; until done

        pop     DX              ; restore quotient from stack
        pop     CX              ; ...
        pop     BX              ; ...
        pop     AX              ; ...
        pop     DI              ; load high word
        shr     DI,1            ; get top bit of quotient
        pop     SI              ; restore exponent of result
        pop     DI              ; restore sign
        mov     SP,BP           ; clean up the stack
        _if     c               ; if top bit of quotient set
          rcr   AX,1            ; - shift fraction right 1 bit
          rcr   BX,1            ; - ...
          rcr   CX,1            ; - ...
          rcr   DX,1            ; - ...
          adc   DX,0            ; - round up
          adc   CX,0            ; - ...
          adc   BX,0            ; - ...
          adc   AX,0            ; - ...
          inc   SI              ; - increment exponent
        _endif                  ; endif
        dec     SI              ; decrement exponent
        _if     le              ; if exponent is negative (denormal number)
          _loop                 ; - loop
            shr   AX,1          ; - - shift number right
            rcr   BX,1          ; - - ...
            rcr   CX,1          ; - - ...
            rcr   DX,1          ; - - ...
            inc   SI            ; - - increment exponent
          _until  ge            ; - until back to 0
          sub   SI,SI           ; - set exponent to 0
        _endif                  ; endif
        or      SI,DI           ; merge sign in with exponent
        pop     BP              ; restore BP
ifdef _BUILDING_MATHLIB
        pop     DS              ; restore DS
endif
        ret                     ; return

        endproc ___LDD

normalize_opnd proc     near
;       operand is on the stack pointed to by DI

        xchg    DI,BP           ; place address of operand in BP
        _loop                   ; loop (normalize it)
          or    BX,BX           ; - check high word for 0
          _quif ne              ; - quit if not zero
          xchg  [BP],BX         ; - shift operand left 16 bits
          xchg  2[BP],BX        ; - ...
          xchg  4[BP],BX        ; - ...
          sub   DX,16           ; - decrement exponent by 16
        _endloop                ; endloop
        _loop                   ; loop (normalize it)
          or    BX,BX           ; - check for implied 1 bit
          _quif s               ; - quit if its on
          shl   word ptr [BP],1 ; - shift fraction left
          rcl   word ptr 2[BP],1; - ...
          rcl   word ptr 4[BP],1; - ...
          _rcl  BX,1            ; - ...
          dec   DX              ; - decrement exponent
        _endloop                ; endloop
        mov     6[BP],BX        ; save high order word
        xchg    DI,BP           ; restore address of operand
        ret                     ; return
normalize_opnd endp


ifdef _BUILDING_MATHLIB

        endmod

        endf    equ end
else
        endf    equ <>

endif

endf

⌨️ 快捷键说明

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