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 + -
显示快捷键?