sqrt086.asm

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

ASM
359
字号
        dec     DX              ; restore DX
        _loop                   ; loop
          div   SI              ; - calculate newer estimate
          dec   SI              ; - want estimate to be within one
          cmp   SI,AX           ; -
          _quif na              ; - quit if estimate good enough
          inc   SI              ; -
          add   SI,AX           ; - calculate new estimate as (old+new)/2
          rcr   SI,1            ; - ...
          mov   DX,CX           ; - restore operand
          mov   AX,BX           ; - ...
        _endloop                ; endloop
        inc     SI              ; restore divisor
        push    AX              ; save word of quotient
        mov     AX,BP           ; get next word of operand
        div     SI              ; calculate next word of quotient
        pop     DX              ; restore high word of quotient
;
;       SI:0   estimate is too small
;       DX:AX estimate is too large
;       calculate new estimate as (SI:0+DX:AX)/2
;
        add     SI,DX           ; ...
        stc                     ; divide by 2
        rcr     SI,1            ; ...
        rcr     AX,1            ; ...
        mov     CX,AX           ; save low word of result
;
;  square SI:CX and subtract from operand to see if result needs adjusting
;
        mul     AX              ; multiply low*low
        sub     DI,AX           ; subtract from operand
        sbb     BP,DX           ; ...
        sbb     BX,0            ; ...
        mov     AX,CX           ; multiply low*high
        mul     SI              ; ..
        sub     BP,AX           ; subtract from operand
        sbb     BX,DX           ; ...
        sub     BP,AX           ; subtract from operand again
        sbb     BX,DX           ; ...
        mov     AX,SI           ; multiply high*high
        mul     SI              ; ...
        sub     BX,AX           ; subtract from operand
        mov     DX,CX           ; save low word of result
;
;       BX:BP:DI contains the remainder, check to see if needs adjusting
;
        mov     AX,SI           ; get high word of new estimate
        _if     ns              ; if top word is not negative
          _loop                 ; - loop
            add   DX,1          ; - - adjust new estimate
            adc   AX,0          ; - - overflow to high word of new estimate
            sub   DI,CX         ; - - subtract divisor from remainder
            sbb   BP,SI         ; - - until we get a borrow
            sbb   BX,0          ; - - ...
          _until  c             ; - until we get a borrow
        _endif                  ; endif
        _loop                   ; loop
          sub     DX,1          ; - decrement low word of new estimate
          sbb     AX,0          ; - borrow from high word of new estimate
          add     DI,CX         ; - add back on
          adc     BP,SI         ; - ...
          adc     BX,0          ; - ...
        _until  c               ; until remainder < divisor
sqrt5:  pop     BX              ; get guard word
        push    AX              ; save high word of new estimate
        push    DX              ; save second word of new estimate
        cmp     SI,BP           ; if this will cause divide overflow
        _if     e               ; then
          mov     AX,-1         ; - estimate is FFFF
        _else                   ; else
          mov     DX,BP         ; - get remainder
          mov     AX,DI         ; - ...
          div     SI            ; - estimate next word of result
        _endif                  ; endif
;
;       remainder is in BP:DI:BX
;
        push    AX              ; save this estimate
        mul     CX              ; multiply estimate (AX) by divisor(SI:CX)
        sub     BX,AX           ; and subtract from remainder
        sbb     DI,DX           ; ...
        sbb     BP,0            ; ...
        pop     AX              ; restore estimate
        push    BX              ; save low word of remainder
        mov     BX,AX           ; save estimate
        mul     SI              ; multiply by high word of divisor
        sub     DI,AX           ; and subtract
        sbb     BP,DX           ; ...
        pop     AX              ; restore low word of remainder
;
;       we should never get an estimate that is too small (but just in case)
;       remainder is in BP:DI:AX
;
        pop     DX              ; restore second word of new estimate
        push    BP              ; save high word of remainder
        mov     BP,SP           ; get access to stack
        _if     nc              ; if no carry (estimate too small)
          _loop                 ; - loop
            add   BX,1          ; - - increment estimate
            adc   DX,0          ; - - overflow to next higher word
            adc   word ptr 2[BP],0; - - ...
            sub   AX,CX         ; - - subtract divisor from remainder
            sbb   DI,SI         ; - - ...
            sbb   word ptr 0[BP],0; - - ...
          _until  c             ; - until we did it one too many times
        _endif                  ; endif
        _loop                   ; loop (estimate was too big)
          sub   BX,1            ; - decrement estimate
          sbb   DX,0            ; - borrow from next higher word
          sbb   word ptr 2[BP],0; - ...
          add   AX,CX           ; - add divisor back to remainder
          adc   DI,SI           ; - ...
          adc   word ptr 0[BP],0; - ...
        _until  c               ; until estimate is correct
        pop     BP              ; clean up stack
        push    DX              ; save second word of new estimate
        cmp     SI,DI           ; if this will cause divide overflow
        _if     e               ; then
          mov   AX,-1           ; - estimate is FFFF
        _else                   ; else
          mov   DX,DI           ; - get remainder
          div   SI              ; - estimate last word of new estimate
        _endif                  ; endif
        pop     DX              ; restore second word of new estimate
        pop     DI              ; restore high word of new estimate
;
;       DI:DX:BX:AX             ; is our new estimate
;       SI:CX                   ; was our original estimate
;
        add     CX,DX           ; add the two estimates together
        adc     SI,DI           ; ...
sqrt7:  rcr     SI,1            ; and divide by 2
        rcr     CX,1            ; ...
        rcr     BX,1            ; ...
        rcr     AX,1            ; ...
        adc     AX,0            ; round up
        adc     BX,0
        adc     CX,0
        adc     SI,0

sqrt8:  pop     DI              ; restore address of operand
        mov     [DI],AX         ; store result
        mov     2[DI],BX        ; ...
        mov     4[DI],CX        ; ...
        mov     6[DI],SI        ; ...

sqrt9:  pop     BX              ; restore BX
        pop     CX              ; restore CX
        pop     DX              ; restore DX
        pop     SI              ; restore SI
        pop     DI              ; restore DI
        pop     BP              ; restore BP
        ret                     ; return to caller
        endproc __sqrt

ifdef _BUILDING_MATHLIB

EMUL_VERSION equ 1

include xception.inc
include fstatus.inc

        xref    F8InvalidOp
        xref    F8OverFlow

include ldfd086.asm
include fdld086.asm

        endmod

        endf    equ end
else
        endf    equ <>

endif

endf

⌨️ 快捷键说明

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