fdmth086.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 1,056 行 · 第 1/3 页
ASM
1,056 行
or SI,CX
or SI,DI
jne add_norm
add SP,8 ; - clean up stack
pop DI ; - restore DI
pop BP ; - restore bp
sub AX,AX ; - set answer to 0
sub BX,BX ; - . . .
sub CX,CX ; - . . .
sub DX,DX ; - . . .
ret ; - return
_endif
neg DH ; - sign is that of other operand
not AL ; - negate the fraction
not BX ; - . . .
not CX ; - . . .
not DI ; - . . .
neg AH ; - (considering the guard bit as an extension)
sbb DI,-1 ; - . . .
sbb CX,-1 ; - . . .
sbb BX,-1 ; - . . .
sbb AL,-1 ; - . . .
add_norm: ; normalizes the mantissa against bit 6
add BP,0010h ; prepare exponent
;<> please note that this will overflow if the exponent is very close to its
;<> maximum size but not too large to overflow under normal circumstances.
;<> since we allow an 11 bit exponent, then, the largest exponent one can
;<> handle with this routine is (10^) 1022.
_shl AH,1 ; get guard bit
_loop ; loop
_rcl DI,1 ; - shift result left
_rcl CX,1
_rcl BX,1
_rcl AL,1
sub BP,0010h ; - decrement exponent
jbe add_uflow ; - ******* handle underflow *******
test AL,20h ; until msb is in bit 6
_until ne
and AL,1Fh ; turn off implied one bit
push DX ; push sign
mov DX,DI
jmp fin_up
; over/underflow entry points for __FDA and __FDS
add_oflow:
mov AX,DX ; put sign into ax
add SP,8 ; clean up stack
pop DI ; restore DI
pop BP ; restore bp
jmp F8OverFlow ; handle overflow
add_uflow:
add SP,8 ; clean up stack
pop DI ; restore DI
pop BP ; restore bp
jmp F8UnderFlow ; handle underflow
endproc __FDA
;
; __FDM
;
; Note that if the real pointed to by DI has few sig digits,
; a short cut is taken.
;
defpe __FDM
go_to fdmul
__FDM87:
fld qword ptr ss:[SI] ; load operand 2
push BP ; save BP
mov BP,SP ; get access to stack
push AX ; push operand 1
push BX ; . . .
push CX ; . . .
push DX ; . . .
fmul qword ptr -8[BP]; - multiply by operand 1
jmp _ret87 ; goto common epilogue
__FDMemu:
push BP ; save BP
push DI ; save DI
; f8split
push AX ; push operand 1 onto stack
push BX ; . . .
push CX ; . . .
push DX ; . . .
mov DI,SP ; get address of operand 1
_guess ; guess
mov BX,AX ; - get most sig word of op1
mov AX,ss:6[SI] ; - get most sig word of op2
mov DL,AL ; - save mantissa-holding part
mov DH,BL ; - save mantissa-holding part
mov cl,bh ; - save sign
and BX,7FF0h ; - isolate exponent
_quif e ; - quif zero
mov ch,ah ; - save sign
and AX,7FF0h ; - isolate exponent
_quif e ; - quif zero
and cx,8080h ; - only want sign bits
xor dx,1010h ; - set implied one bit of mant.
xor DL,AL ; - . . .
xor DH,BL ; - . . .
_admit ; admit: one operand is zero
add SP,8 ; - clean up stack
pop DI ; - restore DI
pop BP ; - restore bp
sub AX,AX ; - set result to 0
sub BX,BX ; - . . .
sub CX,CX ; - . . .
sub DX,DX ; - . . .
ret ; - return
_endguess ; endguess
add CH,CL ; determine sign of result
_guess ; guess: OK
add AX,BX ; - determine exponent of result
sub ax,3ff0h ; - remove extra bias
_quif e ; - FP underflow if exponent = 0
cmp ax,0c000h ; - if exponent >= $c000
_quif ae ; - then FP underflow
_admit ; admit: underflow
add SP,8 ; - clean up stack
pop DI ; - restore DI
pop BP ; - restore bp
jmp F8UnderFlow
_endguess ; endguess
cmp ax,7ff0h ; if $7ff0 >= exponent > $c000
_if ae ; then FP overflow
mov AX,CX ; - put sign into ax
add SP,8 ; - clean up stack
pop DI ; - restore DI
pop BP ; - restore bp
jmp F8OverFlow ; - handle overflow
_endif ; endif
push CX ; push sign
push AX ; push exponent
mov BX,ss:[DI] ; get low order word of op_1
or BX,BX ; if it is zero
_if e ; then
xchg SI,DI ; - flip op_1 and op_2 around
xchg DL,DH ; - . . .
_endif ; endif
sub AX,AX ; clear out AX
mov AL,DH ; set AX up with high order mant of op_1
push AX ; save high order mant
push ss:4[DI] ; save rest of op_1
push ss:2[DI] ; . . .
push ss:[DI] ; . . .
sub BX,BX ; clear out a word
push BX ; move two clear words onto stack
push BX
mov BP,SP ; BP points at empty word and op_1
mov AL,DL ; set AX up with high order mant of op_2
push AX ; save high order mant
push ss:4[SI] ; save rest of op_2
push ss:2[SI] ; . . .
mov BX,ss:[SI] ; . . .
_guess ; guess: multiplier has lots of 0's in it
mov CX,0300h ; - set loop count
or BX,BX ; - check multiplier
_quif ne ; - quit if not zero
pop BX ; - get next word of multiplier
mov CH,2 ; - set loop count
or BX,BX ; - check multiplier
_quif ne ; - quit if not zero
pop BX ; - get next word of multiplier
mov CH,1 ; - set loop count
_endguess ; endguess
; result will be kept in CL:DI:SI:2[BP]:0[BP]
sub SI,SI ; clear out SI
mov DI,SI ; clear out DI
or BX,BX ; if low order multiplier non-zero
_if ne ; then
mov AX,4[BP] ; - get low word of op_1
mul BX ; - multiply low word by A
mov 0[BP],DX ; - save high order word of result
mov AX,6[BP] ; - get next lowest word of op_1
mul BX ; - multiply this word by A
add 0[BP],AX ; - add product onto result
adc DI,DX ; - . . .
mov AX,8[BP] ; - get next lowest word of op_1
mul BX ; - multiply this word by A
add DI,AX ; - add product onto result
adc SI,DX ; - . . .
mov 2[BP],DI ; - save result
sub DI,DI ; - set back to 0
mov AX,10[BP] ; - get highest word of op_1
mul BX ; - multiply this word by A
add SI,AX ; - add product onto result
adc DI,DX ; - . . .
_endif ; endif
_loop ; loop
dec CH ; - decrement loop count
pop BX ; - lowest word of op_1 not used so far
or BX,BX ; - check it (call it A) for zero
je shift_16 ; - skip and shift result right if 0
mov AX,4[BP] ; - get low word of op_1
mul BX ; - multiply low word by A
add [BP],AX ; - add product onto result
adc 2[BP],DX ; - . . .
adc SI,0 ; - carry through as neccesary
adc DI,0 ; - . . .
mov AX,6[BP] ; - get next lowest word of op_1
mul BX ; - multiply this word by A
add 2[BP],AX ; - add product onto result
adc SI,DX ; - . . .
adc DI,0 ; - carry through as necessary
mov AX,8[BP] ; - get next lowest word of op_1
mul BX ; - multiply this word by A
add SI,AX ; - add product onto result
adc DI,DX ; - . . .
adc CL,0 ; - carry through as necessary
mov AX,10[BP] ; - get highest word of op_1
cmp CH,0 ; - check loop count
_quif e ; - quit if muliplied 4 times
mul BX ; - multiply this word by A
add DI,AX ; - add product onto result
adc CL,DL ; - . . .
shift_16:
mov AX,2[BP] ; - shift result right by 1 word
mov [BP],AX ; - . . .
mov 2[BP],SI ; - . . .
mov SI,DI ; - . . .
mov DI,CX ; - . . .
and DI,00FFh ; (we only move low word)
mov CL,0 ; - . . .
_endloop ; endloop
mul BL ; mulitply 2 most significant bytes
add AX,DI ; and add to the result
pop DX ; get low order words of result
pop CX ; . . .
mov BX,SI ; . . .
add SP,8 ; remove operand from stack
shr AX,1 ; - shift result right 3 times
rcr BX,1 ; - . . .
rcr CX,1 ; - . . .
rcr DX,1 ; - . . .
shr AX,1 ; - . . .
rcr BX,1 ; - . . .
rcr CX,1 ; - . . .
rcr DX,1 ; - . . .
shr AX,1 ; - . . .
rcr BX,1 ; - . . .
rcr CX,1 ; - . . .
rcr DX,1 ; - . . .
pop BP ; get exponent
test AL,40h ; find out how many sig bits we got
_if ne
add BP,0010h ; - increment exponent
shr AL,1 ; - move bits to correct pos in words
rcr BX,1 ; - . . .
rcr CX,1 ; - . . .
rcr DX,1 ; - . . .
_endif ; endif
and AL,1Fh ; clear out implied '1' bit
jmp fin_up ; go to general finish up routine
endproc __FDM
;
; __FDD
;
defpe __FDD
go_to fddiv
__FDDbad_div:
fld qword ptr ss:[SI] ; load operand 2
push BP ; save BP
mov BP,SP ; get access to stack
push AX ; push operand 1
push BX ; . . .
push CX ; . . .
push DX ; . . .
call __fdiv_m64r ; divide op 1 by op 2
sub sp,8 ; rtn popped parm, _ret87 wants it
jmp _ret87 ; goto common epilogue
__FDD87:
fld qword ptr ss:[SI] ; load operand 2
push BP ; save BP
mov BP,SP ; get access to stack
push AX ; push operand 1
push BX ; . . .
push CX ; . . .
push DX ; . . .
fdivr qword ptr -8[BP]; divide operand 1 by operand 2
jmp _ret87 ; goto common epilogue
__FDDemu:
push BP ; save BP
push DI ; save DI
; f8split
push AX ; push operand 1 onto stack
push BX ; . . .
push CX ; . . .
push DX ; . . .
mov DI,SP ; get address of operand 1
_guess ; guess
mov BX,AX ; - get most sig word of op1
mov AX,ss:6[SI] ; - get most sig word of op2
mov DL,AL ; - save mantissa-holding part
mov DH,BL ; - save mantissa-holding part
mov cl,bh ; - save sign
and BX,7FF0h ; - isolate exponent
_quif e ; - quif zero
mov ch,ah ; - save sign
and AX,7FF0h ; - isolate exponent
_quif e ; - quif zero
and cx,8080h ; - only want sign bits
xor dx,1010h ; - set implied one bit of mant.
xor DL,AL ; - . . .
xor DH,BL ; - . . .
_admit ; admit: one of the operands is 0
add SP,8 ; - clean up the stack
pop DI ; - restore DI
pop BP ; - restore BP
or ax,ax ; - if the divisor is zero
_if e ; - then
mov ah,cl ; - - set sign of inf
jmp F8DivZero ; - - return div by zero status
_endif ; - endif
sub AX,AX ; - set result to 0
sub BX,BX ; - . . .
sub CX,CX ; - . . .
sub DX,DX ; - . . .
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?