fldd086.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 502 行 · 第 1/2 页
ASM
502 行
ifdef _BUILDING_MATHLIB
include mdef.inc
include struct.inc
include xception.inc
xref F8DivZero
xref F8InvalidOp
modstart fldd086, word
endif
xdefp __FLDD
xdefp ___LDD
; void __FLDD( long double *op1 , long double *op2, long double *result )
; AX - pointer to op1
; DX - pointer to op2
; BX - pointer for result
;
defp __FLDD
ifdef _BUILDING_MATHLIB
push DS ; save DS
push SS ; fpc code assumes parms are relative to SS
pop DS ; ...
endif
push SI ; save SI
push DI ; save DI
push CX ; save CX
push BX ; save pointer to result
mov SI,AX ; point to op1
mov DI,DX ; point to op2
mov AX,8[SI] ; get exponent+sign of op1
mov DX,8[DI] ; get exponent+sign of op2
lcall ___LDD ; do the divide
pop DI ; restore pointer to result
mov [DI],DX ; store result
mov 2[DI],CX ; ...
mov 4[DI],BX ; ...
mov 6[DI],AX ; ...
mov 8[DI],SI ; ...
pop CX ; restore CX
pop DI ; restore DI
pop SI ; restore SI
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc __FLDD
; input:
; SI - pointer to op1
; DI - pointer to op2
; AX - exponent+sign of op1
; DX - exponent+sign of op2
; output:
; SI - exponent+sign of result
; AX:BX:CX:DX - mantissa
defp ___LDD
ifdef _BUILDING_MATHLIB
push DS ; save DS
push SS ; fpc code assumes parms are relative to SS
pop DS ; ...
endif
sub BX,BX ; indicate not a power of two
_guess ; guess: divide by 0
mov CX,4[DI] ; - check the lower order words
or CX,2[DI] ; - ...
or CX,[DI] ; - ...
_quif ne ; - quit if op2 is not 0
mov BX,6[DI] ; - quit if op2 is not 0
or BX,BX ; - ...
_quif ne ; - ...
test DX,7FFFh ; - quit if exponent is not 0
_quif ne ; - ...
_guess ; - guess: 0/0 (invalid operation)
mov CX,6[SI] ; - - quit if op1 is not 0
or CX,4[SI] ; - - check the lower order words
or CX,2[SI] ; - - ...
or CX,[SI] ; - - ...
_quif ne ; - - quit if op1 is not 0
mov CX,AX ; - - get sign+exponent
_shl CX,1 ; - - place sign in carry
_quif ne ; - - quit if not 0
call F8InvalidOp ; - - process exception
mov SI,0FFFFh ; - - return NaN
mov AX,0C000h ; - - ...
_admit ; - admit: divide by 0
mov SI,AX ; - - get exponent+sign of op1
call F8DivZero ; - - process exception
or SI,7FFFh ; - - return signed infinity
mov AX,8000h ; - - ...
_endguess ; - endguess
sub BX,BX ; - zero rest of fraction
sub CX,CX ; - ...
sub DX,DX ; - ...
ifdef _BUILDING_MATHLIB
pop DS ; - restore DS
endif
ret ; - return
_endguess ; endguess
_guess ; guess: op1 is 0
mov CX,6[SI] ; - quit if op1 is not 0
or CX,CX ; - ...
_quif ne ; - ...
or CX,4[SI] ; - check the lower order words
or CX,2[SI] ; - ...
or CX,[SI] ; - ...
_quif ne ; - quit if op1 is not 0
_shl AX,1 ; - place sign in carry
_if e ; - if operand one is 0
mov BX,AX ; - - return zero
mov DX,AX ; - - ...
mov SI,AX ; - - ...
ifdef _BUILDING_MATHLIB
pop DS ; - - restore DS
endif
ret ; - - return
_endif ; - endif
rcr AX,1 ; - put back the sign
_endguess ; endguess
push BP ; save BP
mov BP,SP ; get pointer to saved BP
mov CX,3 ; set loop count
push CX ; ...
mov CX,AX ; get sign of op1
xor CX,DX ; calc. sign for result
and CX,8000h ; ...
and AH,7Fh ; isolate exponent of op1
and DH,7Fh ; isolate exponent of op2
_guess ; guess: divide by power of 2
cmp BX,8000h ; - quit if divisor is not a power of two
_quif ne ; - ...
or AX,AX ; - quit if op1 is denormal
_quif e ; - ...
or DX,DX ; - quit if op2 is denormal
_quif e ; - ...
mov BX,AX ; - get exponent of op1
sub BX,DX ; - determine exponent of result
add BX,3FFFh ; - add in removed bias
_quif le ; - quit if underflow
cmp BX,7FFFh ; - quit if overflow
je div_oflow ; - ...
mov DI,BX ; - get exponent of result
or DI,CX ; - merge in the sign
mov AX,6[SI] ; - load op1
mov BX,4[SI] ; - ...
mov CX,2[SI] ; - ...
mov DX,[SI] ; - ...
mov SI,DI ; - get exponent+sign
mov SP,BP ; - clean up stack
pop BP ; - restore BP
ifdef _BUILDING_MATHLIB
pop DS ; - restore DS
endif
ret ; - return
_endguess ; endguess
count equ -2 ; loop counter
den equ -10 ; denominator
num equ -18 ; numerator
sign equ -20 ; sign of result
exponent equ -22 ; exponent of result
quot equ -30 ; quotient
mov BX,6[DI] ; get high order word of op2
push BX ; duplicate op2 on the stack
push 4[DI] ; ...
push 2[DI] ; ...
push [DI] ; ...
mov DI,SP ; point to pushed value
or DX,DX ; if op2 is a denormal
_if e ; then
call normalize_opnd ; - normalize op2
_endif ; endif
mov BX,6[SI] ; get high order word of op1
push BX ; duplicate op1 on the stack
push 4[SI] ; ...
push 2[SI] ; ...
push [SI] ; ...
mov DI,SP ; point to pushed value
or AX,AX ; if op1 is a denormal
_if e ; then
xchg AX,DX ; - exchange exponents
call normalize_opnd ; - normalize op1
xchg AX,DX ; - exchange exponents
or DX,DX ; - if other operand is a normal
_if g ; - then
inc AX ; - - adjust exponent
_endif ; - endif
_endif ; endif
_guess ; guess: overflow
sub AX,DX ; - determine exponent of result
add AX,3FFFh ; - add in removed bias
_quif s ; - quit if exponent is negative
cmp AX,7FFFh ; - quit if not overflow
_quif b ; - . . .
div_oflow:mov SI,CX ; - get sign of result
or SI,7FFFh ; - return signed infinity
mov AX,8000h ; - ...
sub BX,BX ; - ...
sub CX,CX ; - ...
sub DX,DX ; - ...
mov SP,BP ; - clean up stack
pop BP ; - restore BP
ifdef _BUILDING_MATHLIB
pop DS ; - restore DS
endif
ret ; - return signed infinity
_endguess ; endguess
cmp AX,-64 ; if exponent is too small
_if l ; then underflow
sub AX,AX ; - set result to 0
mov BX,AX ; - ...
mov CX,AX ; - ...
mov DX,AX ; - ...
mov SI,AX ; - ...
mov SP,BP ; - clean up stack
pop BP ; - restore BP
ifdef _BUILDING_MATHLIB
pop DS ; - restore DS
endif
ret ; - return
_endif ; endif
push CX ; save sign of result
push AX ; save exponent of result
mov DX,num+6[BP] ; get high part of dividend
mov AX,num+4[BP] ; ...
mov SI,den+6[BP] ; get high word of divisor
sub BX,BX ; assume high word of quotient = 0
cmp SI,DX ; if divisor <= high word of dividend
_if be ; then
sub DX,SI ; - subtract divisor from dividend
inc BX ; - set high word of quotient to 1
_endif ; endif
push BX ; save high word of quotient (quot+6[BP])
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?