sqrt086.asm

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

ASM
359
字号

ifdef _BUILDING_MATHLIB

include mdef.inc
include struct.inc

        modstart  sqrt086

        xdefp   __sqrtd

;
;      double __sqrtd( double AX BX CX DX );
;
        defp    __sqrtd
        push    SI                      ; save SI
        push    DS                      ; save DS
        sub     SP,10                   ; allocate space for long double
        mov     SI,SS                   ; set DS=SS
        mov     DS,SI                   ; ...
        mov     SI,SP                   ; point DS:SI to long double
        call    __EmuFDLD               ; convert double to long double
        mov     AX,SP                   ; point to long double
        call    __sqrt                  ; calculate square root
        mov     BX,SP                   ; point to long double
        call    __EmuLDFD               ; convert it to double
        add     SP,10                   ; remove long double from stack
        pop     DS                      ; restore DS
        pop     SI                      ; restore SI
        ret                             ; return
        endproc __sqrtd


endif

        xdefp   __sqrt
;
;       __sqrt( long double *AX );
;

__sqrt  proc    near
        push    BP              ; save BP
        push    DI              ; save DI
        push    SI              ; save SI
        push    DX              ; save DX
        push    CX              ; save CX
        push    BX              ; save BX
        mov     SI,AX           ; get address of argument
        mov     CX,8[SI]        ; get exponent

        _guess                          ; guess: special number
          mov   AX,[SI]                 ; - check for 0
          or    AX,2[SI]                ; - ...
          or    AX,4[SI]                ; - ...
          _quif ne                      ; - quit if not 0
          or    AX,6[SI]                ; - ...
          _if   e                       ; - if equal so far
            _shl  CX,1                  ; - - get rid of sign bit
            je    done1                 ; - - answer is 0 if exponent is 0
            rcr   CX,1                  ; - - put back the sign bit
          _endif                        ; - endif
          _guess                        ; - guess: answer is indefinite
            or    AX,AX                 ; - - quit if unnormal
            _quif e                     ; - - ...
;           shl   CX,1                  ; - - get rid of sign bit
;           _quif e                     ; - - quit if denormal
;           rcr   CX,1                  ; - - put back the sign
            cmp   CX,7FFFh              ; - - if +ve infinity
            _if   e                     ; - - then
              shl   AX,1                ; - - - answer is +ve infinity
              je    done1               ; - - - ...
            _endif                      ; - - endif
          _admit                        ; - admit: answer is indefinite
indefinite: mov   word ptr 8[SI],0FFFFh ; - - set result to indefinite
            sub   AX,AX                 ; - - ...
            mov   6[SI],AX              ; - - ...
            mov   4[SI],AX              ; - - ...
            mov   2[SI],AX              ; - - ...
            mov   [SI],AX               ; - - ...
NaN:        or    word ptr 6[SI],0C000h ; - - ...
done1:      jmp   sqrt9                 ; - - and return
          _endguess                     ; - endguess
        _endguess                       ; endguess
        _guess                          ; guess: NaN
          mov   AX,CX                   ; - get exponent
          and   AX,7FFFh                ; - get rid of sign
          cmp   AX,7FFFh                ; - check for NaN
          je    NaN                     ; - result stays as a NaN
          _shl  CX,1                    ; - get rid of sign bit
          jc    indefinite              ; - result of -ve number is indefinite
          shr   CX,1                    ; - restore sign
          _quif e                       ; - quit if number is denormal
          mov   AX,6[SI]                ; - check for unnormal number
          _shl  AX,1                    ; - top bit should be on
          jnc   indefinite              ; - number is a unnormal
        _endguess                       ; endguess

        push    SI              ; save address of operand
        sub     AX,AX           ; zero guard bits
        mov     DX,6[SI]        ; get high part of operand
        mov     BX,4[SI]        ; ...
        mov     BP,2[SI]        ; ...
        mov     DI,[SI]         ; ...

        sub     CX,3FFFh        ; remove bias
        sar     CX,1            ; divide by 2
        _if     nc              ; if exponent is even
          shr   DX,1            ; - divide argument by 2
          rcr   BX,1            ; - ...
          rcr   BP,1            ; - ...
          rcr   DI,1            ; - ...
          rcr   AX,1            ; - save guard bit
        _endif                  ; endif
        add     CX,3FFFh        ; add bias back in
        mov     8[SI],CX        ; store exponent
        push    AX              ; save guard bit

        mov     CX,DX           ; save operand
        mov     AX,BX           ; ...

        mov     SI,DX           ; get high order word
        stc                     ; calculate initial estimate
        rcr     SI,1            ; ...
        inc     DX              ; check for DX=FFFFh
        _if     e               ; if (high word was -1)
          dec   DX              ; - set DX back to -1
          cmp   BX,SI           ; - if next word is -1
          _if   e               ; - then
            cmp   BP,SI         ; - - if third word is also -1
            _if   e             ; - - then
              cmp   DI,SI       ; - - - if last word is -1
              _if   e           ; - - - then answer is all ones
                jmp   sqrt8     ; - - - - ...
              _endif            ; - - - endif
            _endif              ; - - endif
            pop   AX            ; - - get guard word
            mov   CX,BX         ; - - get second word
            mov   BX,BP         ; - - get third word
            mov   AX,DI         ; - - get last word
            stc                 ; - - set carry
            jmp   sqrt7         ; - - calculate final answer
          _endif                ; - endif
          mov   CX,BX           ; -
          stc                   ; -
          rcr   CX,1            ; - calc. second word of estimate
          mov   AX,CX           ; - multiply to see if estimate is too big
          mul   CX              ; - ...
          mov   SI,CX           ; - ...
          add   SI,SI           ; - ...
          inc   SI              ; - ...
          sub   DX,CX           ; - ...
          sbb   SI,0            ; - ...
          sub   DX,CX           ; - ...
          sbb   SI,0            ; - ...
          sub   DI,AX           ; - subtract result from operand
          sbb   BP,DX           ; - ...
          sbb   BX,SI           ; - ...
          push  CX              ; - save first estimate
          mov   DX,CX           ; - value for new estimate
          _if   nc              ; - if our estimate is too small
            _loop               ; - - loop
              inc   DX          ; - - - increment estimate
              sub   DI,CX       ; - - - adjust remainder
              sbb   BP,0FFFFh   ; - - - ...
              sbb   BX,0        ; - - - ...
            _until  c           ; - - until OK
          _endif                ; - endif
          _loop                 ; - loop
            dec   DX            ; - - decrement estimate
            add   DI,CX         ; - - adjust remainder
            adc   BP,0FFFFh     ; - - ...
            adc   BX,0          ; - - ...
          _until  c             ; - until OK
          pop   CX              ; - restore first estimate
          mov   SI,-1           ; - reset top word to -1
          mov   AX,SI           ; - place in AX as well
          jmp   short sqrt5     ; - continue
        _endif                  ; endif

; else high word not -1, then

⌨️ 快捷键说明

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