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