fdmth386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 485 行 · 第 1/2 页
ASM
485 行
rcr EAX,1 ; - - - ...
inc BP ; - - - increment exponent
cmp BP,07FFh ; - - - quit if overflow
je add_oflow ; - - - . . .
_endif ; - - endif
_endif ; - endif
and EDX,000FFFFFh ; - get rid of implied 1 bit
mov ECX,EBP ; - get sign
shl EBP,21 ; - shift exponent to top
_shl ECX,1 ; - get sign
rcr EBP,1 ; - put it in
or EDX,EBP ; - put exponent and sign into result
_endif ; endif
pop ESI ; restore ESI
pop EDI ; restore EDI
pop EBP ; restore EBP
ret ; return
denormal: ; handle denormal
_shl EBP,1 ; get sign
rcr EDX,1 ; put it in result
rcr EAX,1 ; ...
pop ESI ; restore ESI
pop EDI ; restore EDI
pop EBP ; restore EBP
ret ; return
add_oflow: ; handle overflow
mov EAX,EBP ; get proper sign for infinity
pop ESI ; restore ESI
pop EDI ; restore EDI
pop EBP ; restore EBP
jmp F8OverFlow ; handle overflow
endproc __FDA
endproc __FDS
;=====================================================================
;<> multiplies X by Y and places result in C.
;<> X2 and X1 represent the high and low words of X. Similarly for Y and C
;<> Special care is taken to use only six registers, so the code is a bit
;<> obscure
defpe __FDM
_guess ; guess: one of the operands is 0
or EAX,EAX ; - see if first arg is zero
_quif ne ; - quit if op1 is not 0
_shl EDX,1 ; - place sign in carry
_if e ; - if operand one is 0
ret ; - - return
_endif ; - endif
rcr EDX,1 ; - restore sign
_endguess ; endguess
_guess ; guess: op2 is 0
or EBX,EBX ; - quit if op2 is not 0
_quif ne ; - . . .
_shl ECX,1 ; - place sign in carry
_if e ; - if operand 2 is 0
sub EAX,EAX ; - - set result to 0
sub EDX,EDX ; - - . . .
ret ; - - return
_endif ; - endif
rcr ECX,1 ; - restore sign of op2
_endguess ; endguess
cmp byte ptr __real87,0; if 8087 not to be used
je short __FDMemu ; then emulate
__FDM87:
push EDX ; push operand 1
push EAX ; . . .
fld qword ptr [ESP] ; load operand 1
push ECX ; push operand 2
push EBX ; . . .
fmul qword ptr [ESP] ; multiply operand 1 by operand 2
jmp _ret87 ; goto common epilogue
__FDMemu:
push EBP ; save EBP
push EDI ; save EDI
push ESI ; save EDI
mov EDI,EDX ; get high part of op1
mov ESI,ECX ; get high part of op2
sar EDI,20 ; shift exponent to bottom, duplicating sign
sar ECX,20 ; shift exponent to bottom, duplicating sign
and EDI,0800007FFh ; isolate signs and exponent
and ECX,0800007FFh ; ...
rol EDI,16 ; rotate signs to bottom
rol ECX,16 ; ...
add CX,DI ; calc sign of result
rol EDI,16 ; rotate signs to top
rol ECX,16 ; ...
and EDX,000FFFFFh ; isolate fraction
and ESI,000FFFFFh ; isolate fraction
or DI,DI ; if op1 is a denormal
_if e ; then
inc DI ; - adjust exponent by 1
_loop ; - loop (normalize it) 27-jul-90
dec DI ; - - decrement exponent
_shl EAX,1 ; - - shift left 1
_rcl EDX,1 ; - - ...
test EDX,00100000h ; - - check for implied 1 bit
_until ne ; - until normalized
_endif ; endif
or EDX,00100000h ; turn on implied 1 bit
or CX,CX ; if op2 is a denormal
_if e ; then
inc CX ; - adjust exponent by 1
_loop ; - loop (normalize it) 27-jul-90
dec CX ; - - decrement exponent
_shl EBX,1 ; - - shift left 1
_rcl ESI,1 ; - - ...
test ESI,00100000h ; - - check for implied 1 bit
_until ne ; - until normalized
_endif ; endif
or ESI,00100000h ; turn on implied 1 bit
_guess ; guess: overflow
add CX,DI ; - determine exponent of result
sub CX,03ffh ; - remove extra bias
_quif s ; - quit if exponent is negative
cmp CX,07FFh ; - quit if not overflow
_quif b ; - . . .
mov EAX,ECX ; - put sign into EAX
pop ESI ; - restore ESI
pop EDI ; - restore EDI
pop EBP ; - restore EBP
jmp F8OverFlow ; - handle overflow
_endguess ; endguess
cmp CX,-53 ; if exponent is too small
_if l ; then underflow
pop ESI ; - restore ESI
pop EDI ; - restore EDI
pop EBP ; - restore EBP
jmp F8UnderFlow ; - handle underflow
_endif ; endif
push ECX ; save sign and exponent
mov CL,11 ; shift fractions to top of registers
shld EDX,EAX,CL ; ...
shld EAX,EBP,CL ; ...
and EAX,0FFFFF800h ; ...
shld ESI,EBX,CL ; ...
shld EBX,EBP,CL ; ...
and EBX,0FFFFF800h ; ...
sub EBP,EBP ; zero EBP
push ESI ; save high part of op2
push EDX ; save high part of op1
push EAX ; save low part of op1
mul EBX ; low part of op1 * low part of op2
xchg EAX,ESI ; ESI becomes start of the sticky bits
mov ECX,EDX ; save high part of result
pop EDX ; restore low part of op1
mul EDX ; low part of op1 * high part of op2
mov EDI,EDX ; save high part of product
add ECX,EAX ; add partial product
adc EDI,EBP ; ...
adc EBP,EBP ; ...
pop EAX ; restore high part of op1
xchg EAX,EBX ; flip with low part of op2
mul EBX ; high part of op1 * low part of op2
add ECX,EAX ; add partial product
adc EDI,EDX ; ...
adc EBP,0 ; ...
mov EAX,EBX ; get high part of op1
pop EDX ; restore high part of op2
mul EDX ; high part of op1 * high part of op2
add EAX,EDI ; add partial product
adc EDX,EBP ; ...
sub EBX,EBX ; get zero for zero fill
mov CL,10 ; shift result over
shrd EBX,EAX,CL ; ... get sticky bits 18-feb-91
shrd EAX,EDX,CL ; ...
shrd EDX,EBX,CL ; ...
pop ECX ; restore sign and exponent
_loop ; loop
test EDX,00200000h ; - test to see if bit in exponent field
_quif e ; - quit if not
shr EDX,1 ; - shift result right
rcr EAX,1 ; - . . .
rcr EBX,1 ; - save carry
inc CX ; - inc exponent for every shift
cmp CX,07FFh ; - quit if overflow
je mul_oflow ; - . . .
_endloop ; endloop
_shl EBX,1 ; get guard bit
_if c ; if set
_if e ; - if rest of sticky bits are 0
or ESI,ESI ; - - check the bottom sticky bits
setne BL ; - - ...
shr EBX,1 ; - - if all sticky bits are zero
_if nc ; - - then
mov ESI,EAX ; - - - get bottom bit of result
shr ESI,1 ; - - - as rounding bit
_endif ; - - endif
_endif ; - endif
adc EAX,0 ; - round up
adc EDX,0 ; - ...
test EDX,00200000h ; - test to see if bit in exponent field
_if ne ; - if fraction overflowed
shr EDX,1 ; - - shift right
rcr EAX,1 ; - - ...
inc CX ; - - increment exponent
cmp CX,07FFh ; - - quit if overflow
je mul_oflow ; - - . . .
_endif ; - endif
_endif ; endif
or CX,CX ; if exponent <= 0
_if le ; then (denormal result)
_if e ; - if exponent = 0
mov CL,1 ; - - set shift count to 1
_else ; - else
neg CX ; - - negate to get shift count
dec CX ; - - adjust
_endif ; - endif
sub EBX,EBX ; - for zero fill
shrd EAX,EDX,CL ; - align the fraction
shrd EDX,EBX,CL ; - ...
sub CX,CX ; - set exponent to 0
_endif ; endif
and EDX,000FFFFFh ; isolate fraction
mov ESI,ECX ; get copy of sign
ror ECX,11 ; get exponent
_shl ESI,1 ; get sign
rcr ECX,1 ; put it in
and ECX,0FFF00000h ; isolate sign and exponent
or EDX,ECX ; place it in result
pop ESI ; restore ESI
pop EDI ; restore EDI
pop EBP ; restore EBP
ret ; return
mul_oflow: ; overflow
mov EAX,ECX ; get sign of infinity
pop ESI ; restore ESI
pop EDI ; restore EDI
pop EBP ; restore EBP
jmp F8OverFlow ; handle overflow
endproc __FDM
endmod
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?