sqrtf.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 167 行

ASM
167
字号
;*****************************************************************************
;*
;*                            Open Watcom Project
;*
;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;*  ========================================================================
;*
;*    This file contains Original Code and/or Modifications of Original
;*    Code as defined in and that are subject to the Sybase Open Watcom
;*    Public License version 1.0 (the 'License'). You may not use this file
;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;*    provided with the Original Code and Modifications, and is also
;*    available at www.sybase.com/developer/opensource.
;*
;*    The Original Code and all software distributed under the License are
;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;*    NON-INFRINGEMENT. Please see the License for the specific language
;*    governing rights and limitations under the License.
;*
;*  ========================================================================
;*
;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;*               DESCRIBE IT HERE!
;*
;*****************************************************************************


include mdef.inc
include struct.inc

        modstart        sqrtf,WORD

        xdefp   sqrtf_          ; calc single precision sqrt(fac1)


        defp    sqrtf_
ifdef __386__
        push    EBX             ; save registers
        push    ECX             ; ...
        push    EDX             ; ...
        push    ESI             ; ...
        _guess                  ; guess: non-zero
          add   EAX,EAX         ; - get rid of sign bit
          _quif e               ; - quit if number is 0
          mov   ECX,EAX         ; - get value
          shl   EAX,7           ; - get rid of exponent
          or    EAX,80000000h   ; - turn on implied 1-bit
          shr   ECX,24          ; - get rid of fraction
          sub   CL,7Fh          ; - remove bias
          sar   CL,1            ; - divide by 2
          _if   nc              ; - if exponent is even
            shr   EAX,1         ; - - divide argument by 2
          _endif                ; - endif
          add   CL,7Fh          ; - add bias
          mov   ESI,EAX         ; - get fraction
          stc                   ; - calculate initial estimate
          rcr   ESI,1           ; - ...
          mov   EBX,EAX         ; - save operand
          mov   EDX,EAX         ; - set up for divide
          _loop                 ; - loop (until estimate is correct)
            sub   EAX,EAX       ; - - zero low word
            div   ESI           ; - - calculate newer estimate
            dec   ESI           ; - - want estimate to be within one
            cmp   ESI,EAX       ; - - ...
            _quif na            ; - - quit if estimate good enough
            inc   ESI           ; - -
            add   ESI,EAX       ; - - calc. new estimate as (old+new)/2
            rcr   ESI,1         ; - - ...
            mov   EDX,EBX       ; - - restore operand
          _endloop              ; - endloop
          shl   EAX,1           ; - get rid of implied one bit
          and   AH,0FEh         ; - isolate fraction bits
          mov   AL,CL           ; - get exponent
          ror   EAX,9           ; - rotate into place
        _endguess               ; endguess
        pop     ESI             ; restore registers
        pop     EDX             ; ...
        pop     ECX             ; ...
        pop     EBX             ; ...
else
        push    BX              ; save registers
        push    CX              ; ...
        push    SI              ; ...
        push    DI              ; ...
        _guess                  ; guess: non-zero
          mov   CX,DX           ; - get high word
          and   CH,7Fh          ; - remove sign bit
          or    CX,AX           ; - or in low order word
          _quif e               ; - quit if number is 0
          mov   CX,DX           ; - get exponent
          shl   CX,1            ; - ...
          mov   CL,CH           ; - get exponent
          mov   DH,DL           ; - shift fraction up
          mov   DL,AH           ; - ...
          mov   AH,AL           ; - ...
          mov   AL,0            ; - ...
          or    DH,80h          ; - turn on implied 1-bit
          sub   CL,7Fh          ; - remove bias
          sar   CL,1            ; - divide by 2
          _if   nc              ; - if exponent is even
            shr   DX,1          ; - - divide argument by 2
            rcr   AX,1          ; - - ...
          _endif                ; - endif
          add   CL,7Fh          ; - add bias
          mov   BX,AX           ; - save value
          mov   DI,DX           ; - ...
          mov   SI,DX           ; - get high order word of fraction
          stc                   ; - calculate initial estimate
          rcr   SI,1            ; - ...
          inc   DX              ; - check for DX=FFFFh
          _if   e               ; - if high word was -1
            dec   DX            ; - - restore DX
            stc                 ; - - calc. second word of estimate
            rcr   AX,1          ; - - ...
          _else                 ; - else
            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       ; - - - calc. new estimate as (old+new)/2
              rcr   SI,1        ; - - - ...
              mov   DX,DI       ; - - - restore operand
              mov   AX,BX       ; - - - ...
            _endloop            ; - - endloop
            inc   SI            ; - - restore divisor
            push  AX            ; - - save word of quotient
            sub   AX,AX         ; - - zero low word
            div   SI            ; - - calc. 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   DX,SI         ; - - ...
            stc                 ; - - divide by 2
            rcr   DX,1          ; - - ...
            rcr   AX,1          ; - - ...
          _endif                ; - endif
          add   AX,AX           ; - get rid of implied one bit
          adc   DX,DX           ; - ...
          mov   AL,AH           ; - right shift by 8
          mov   AH,DL           ; - ...
          mov   DL,DH           ; - ...
          mov   DH,CL           ; - get exponent
          shr   DX,1            ; - set sign to +ve
          rcr   AX,1            ; - ...
        _endguess               ; endguess
        pop     DI              ; restore registers
        pop     SI              ; ...
        pop     CX              ; ...
        pop     BX              ; ...
endif
        ret                     ; return
        endproc sqrtf_

        endmod
        end

⌨️ 快捷键说明

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