📄 flda086.asm
字号:
xchg SI,DI ; - - flip pointers to arguments
_endif ; - endif
; BP has exponent+sign of largest argument
; DI points to the largest operand
_guess ; - guess: can return operand 1
cmp DX,64 ; - - quit if shift count not too big
_quif be ; - - ...
mov DL,64 ; - - set shift count to 64
or CX,CX ; - - quit if signs of operands are different
_quif s ; - - ...
mov AX,6[DI] ; - - load largest argument
mov BX,4[DI] ; - - ...
mov CX,2[DI] ; - - ...
mov DX,[DI] ; - - ...
mov SI,BP ; - - get exponent+sign
pop BP ; - - restore BP
ifdef _BUILDING_MATHLIB
pop DS ; - - restore DS
endif
ret ; - - return
_endguess ; - endguess
_endif ; endif
; load the smaller argument into registers so we can shift it
; right to align the fractions.
; SI points to the smaller argument.
; DI points to the larger argument.
; DX has amount to shift by to align the fractions.
; BP has exponent + sign of result
; high bit of CX = 1 iff operands have different signs
push CX ; save sign indicator
push DX ; save shift count
push DI ; save DI (pointer to larger operand)
push CX ; save sign indicator
mov AX,6[SI] ; load smallest argument
mov BX,4[SI] ; ...
mov CX,2[SI] ; ...
mov SI,[SI] ; ...
xchg SI,DX ; get shift count into SI
sub DI,DI ; set sticky bits to 0
xchg AX,DI ; AX gets sticky bits
_loop ; loop (for groups of 16 bits)
cmp SI,16 ; - quit if < 16 bits to shift
_quif b ; - ...
or AL,AH ; - move sticky bits to bottom
mov AH,0 ; - zero top sticky bits
or AX,DX ; - set sticky bits
mov DX,CX ; - shift fraction right 16 bits
mov CX,BX ; - ...
mov BX,DI ; - ...
sub DI,DI ; - ...
sub SI,16 ; - adjust shift count
_endloop ; endloop
cmp SI,8 ; if >= 8 bits to move
_if ae ; then
or AL,AH ; - move sticky bits to bottom
mov AH,DL ; - make these the top sticky bits
mov DL,DH ; - shift right 8 bits
mov DH,CL ; - ...
mov CL,CH ; - ...
mov CH,BL ; - ...
mov BL,BH ; - ...
xchg AX,DI ; - put sticky bits into DI
mov BH,AL ; - ...
mov AL,AH ; - ...
mov AH,0 ; - ...
xchg AX,DI ; - get sticky bits back into AX
sub SI,8 ; - adjust shift count
_endif ; endif
_loop ; loop (bit shifting)
or SI,SI ; - quit if shift count = 0
_quif e ; - ...
or AL,AH ; - move sticky bits to bottom
shr DI,1 ; - shift fraction right 1 bit
rcr BX,1 ; - ...
rcr CX,1 ; - ...
rcr DX,1 ; - ...
rcr AH,1 ; - save carry in AH (sticky bits)
dec SI ; - decrement shift count
_endloop ; endloop
xchg AX,DI ; place sticky bits in DI
pop SI ; restore sign
_shl SI,1 ; set carry if operands have different signs
pop SI ; restore pointer to larger operand
_if c ; if operands have different signs
sub DX,[SI] ; - subtract larger operand from smaller one
sbb CX,2[SI] ; - ...
sbb BX,4[SI] ; - ...
sbb AX,6[SI] ; - ...
_if c ; - if borrow
pop SI ; - - restore shift count
push SI ; - - save shift count
not AX ; - - negate the fraction
not BX ; - - ...
not CX ; - - ...
not DX ; - - ...
rol DI,1 ; - - get carry from guard bit
ror DI,1 ; - - ...
; neg DI ; - - negate the sticky bits as well
; _guess ; - - guess: have to round up before negate
; cmp SI,64 ; - - - quit if shift count < 64
; _quif b ; - - - ...
; stc ; - - - increment
; _endguess ; - - endguess
; cmc ; - - complement carry
sbb DX,-1 ; - - add 1 (or zero)
sbb CX,-1 ; - - ...
sbb BX,-1 ; - - ...
sbb AX,-1 ; - - ...
xor BP,8000h ; - - change the sign
_endif ; - endif
xor BP,8000h ; - change the sign
mov SI,AX ; - check for 0
or SI,BX ; - ...
or SI,CX ; - ...
or SI,DX ; - ...
_if e ; - if result is 0
pop BP ; - - clean up stack
pop BP ; - - clean up stack
pop BP ; - - restore BP
ifdef _BUILDING_MATHLIB
pop DS ; - - restore DS
endif
ret ; - - return
_endif ; - endif
_else ; else operands have same signs
add DX,[SI] ; - add larger operand to smaller one
adc CX,2[SI] ; - ...
adc BX,4[SI] ; - ...
adc AX,6[SI] ; - ...
_endif ; endif
pop SI ; restore shift count
mov SI,BP ; get exponent
pop BP ; restore sign indicate
_rcl SI,1 ; get rid of sign bit (and save carry)
rcr BP,1 ; save sign bit
shr SI,1 ; isolate exponent (and reload carry)
_if nc ; if no carry out of the top
je denormal ; - denormal number when exponent hits 0
rol DI,1 ; - set carry from last sticky bit
ror DI,1 ; - ...
_loop ; - loop (normalize)
dec SI ; - - decrement exponent (doesn't change carry)
je denormal ; - - exit if denormal operand
_rcl DX,1 ; - - shift number left 1
_rcl CX,1 ; - - ...
_rcl BX,1 ; - - ...
_rcl AX,1 ; - - ...
_until c ; - until carry
_endif ; endif
inc SI ; bump exponent back up one
stc ; set carry
rcr AX,1 ; shift fraction right once
rcr BX,1 ; ...
rcr CX,1 ; ...
rcr DX,1 ; ...
_if c ; if guard bit is on
test BP,4000h ; - if operands have different signs
_if ne ; - then
; shl DI,1 ; - - get top sticky bit
; _if e ; - - if no more sticky bits
; ror DX,1 ; - - - set carry with bottom bit of DX
; rol DX,1 ; - - - ...
; _endif ; - - endif
; sbb DX,0 ; - - subtract carry from answer
; sbb CX,0 ; - - ...
; sbb BX,0 ; - - ...
; sbb AX,0 ; - - ...
; _if ns ; - - if went from 0x8000 to 0x7fff
; mov AX,BX ; - - - set AX to 0xffff (BX,CX,DX == 0xffff)
; dec SI ; - - - decrement exponent
; _endif ; - - endif
_else ; - else
_shl DI,1 ; - - get top sticky bit
_if e ; - - if no more sticky bits
ror DX,1 ; - - - set carry with bottom bit of DX
rol DX,1 ; - - - ...
_endif ; - - endif
adc DX,0 ; - - add carry into result
adc CX,0 ; - - ...
adc BX,0 ; - - ...
adc AX,0 ; - - ...
_if c ; - - if we got a carry
mov AH,80h ; - - - set fraction to 8000 ...
inc SI ; - - - increment exponent
_endif ; - - endif
_endif ; - endif
_endif ; endif
denormal:
and BP,8000h ; isolate sign
or SI,BP ; merge sign in with exponent
pop BP ; restore BP
ifdef _BUILDING_MATHLIB
pop DS ; restore DS
endif
ret ; return
endproc ___LDA
ifdef _BUILDING_MATHLIB
endmod
endf equ end
else
endf equ <>
endif
endf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -