📄 fp.asm
字号:
mov ax, fpacc.Mantissa[0]
or ax, fpacc.Mantissa[2]
or ax, fpacc.Mantissa[4]
or ax, fpacc.Mantissa[6]
jne FPACCNot0 ; the whole thing is zero.
mov ax, fpop.exponent ;If FPACC is zero, simply
mov fpacc.exponent, ax ; copy FPOP to FPACC.
mov ax, fpop.Mantissa[0]
mov fpacc.Mantissa[0], ax
mov ax, fpop.Mantissa[2]
mov fpacc.Mantissa[2], ax
mov ax, fpop.Mantissa[4]
mov fpacc.Mantissa[4], ax
mov ax, fpop.Mantissa[6]
mov fpacc.Mantissa[6], ax
mov al, fpop.Sign
mov fpacc.Sign, al
jmp Done
FPACCNot0:
mov ax, fpop.Mantissa[0]
or ax, fpop.Mantissa[2]
or ax, fpop.Mantissa[4]
or ax, fpop.Mantissa[6]
jne FPOPNot0
jmp Done
; Adjust the smaller of the two operands so that the exponents of the two
; objects are the same:
FPOPNot0:
mov cx, fpacc.exponent
sub cx, fpop.exponent
js gotoAdjustFPA
jnz AdjustFPOP
jmp Adjusted ;Only if exponents are equal.
gotoAdjustFPA: jmp AdjustFPACC
;
; Since the difference of the exponents is negative, the magnitude of FPOP
; is smaller than the magnitude of fpacc. Adjust FPOP here.
;
AdjustFPOP: cmp cx, 64 ;If greater than 64, forget
jb short By16LoopTest ; it. Sum is equal to FPACC.
jmp Done
;
; If the difference is greater than 16 bits, adjust FPOP a word at a time.
; Note that there may be multiple words adjusted in this fashion.
;
By16Loop: mov ax, fpop.mantissa[2]
mov fpop.mantissa[0], ax
mov ax, fpop.mantissa[4]
mov fpop.mantissa[2], ax
mov ax, fpop.mantissa[6]
mov fpop.mantissa[4], ax
mov fpop.mantissa[6], 0
sub cx, 16
By16LoopTest: cmp cx, 16
jae By16Loop
;
; After adjusting sixteen bits at a time, see if there are at least eight
; bits. Note that this can only occur once, for if you could adjust by
; eight bits twice, you could have adjusted by 16 above.
;
cmp cx, 8
jb NotBy8
mov ax, fpop.mantissa[1]
mov fpop.mantissa[0], ax
mov ax, fpop.mantissa[3]
mov fpop.mantissa[2], ax
mov ax, fpop.mantissa[5]
mov fpop.mantissa[4], ax
mov al, byte ptr fpop.mantissa [7]
mov byte ptr fpop.mantissa [6], al
mov byte ptr fpop.mantissa[7], 0
sub cx, 8
;
; Well, now we're down to a bit at a time.
;
NotBy8: jcxz AdjFPOPDone
;
; Load the mantissa into registers to save processing time.
;
mov ax, fpop.mantissa[6]
mov bx, fpop.mantissa[4]
mov dx, fpop.mantissa[2]
mov si, fpop.mantissa[0]
By1Loop: shr ax, 1
rcr bx, 1
rcr dx, 1
rcr si, 1
loop By1Loop
mov fpop.mantissa[6], ax ;Save result back into
mov fpop.mantissa[4], bx ; fpop.
mov fpop.mantissa[2], dx
mov fpop.mantissa[0], si
AdjFPOPDone: jmp Adjusted
;
;
;
; AdjustFPACC- FPACC was smaller than FPOP, so adjust its bits down here.
; This code is pretty much identical to the above, the same
; comments apply.
;
AdjustFPACC: neg cx ;Take ABS(cx)
cmp cx, 64 ;If greater than 64, forget
jb By16LpTest ; it.
jmp SetFPACC2Zero
;
By16Lp: mov ax, fpacc.mantissa[2]
mov fpacc.mantissa[0], ax
mov ax, fpacc.mantissa[4]
mov fpacc.mantissa[2], ax
mov ax, fpacc.mantissa[6]
mov fpacc.mantissa[4], ax
mov fpacc.mantissa[6], 0
sub cx, 16
By16LpTest: cmp cx, 16
jae By16Lp
;
cmp cx, 8
jb NotBy8a
mov ax, fpacc.mantissa[1]
mov fpacc.mantissa[0], ax
mov ax, fpacc.mantissa[3]
mov fpacc.mantissa[2], ax
mov ax, fpacc.mantissa[5]
mov fpacc.mantissa[4], ax
mov al, byte ptr fpacc.mantissa [7]
mov byte ptr fpacc.mantissa [6], al
mov byte ptr fpacc.mantissa[7], 0
sub cx, 8
;
NotBy8a: jcxz Adjusted
mov ax, fpacc.mantissa[6]
mov bx, fpacc.mantissa[4]
mov dx, fpacc.mantissa[2]
mov si, fpacc.mantissa[0]
By1Lp: shr ax, 1
rcr bx, 1
rcr dx, 1
rcr si, 1
loop By1Lp
mov fpacc.mantissa[6], ax
mov fpacc.mantissa[4], bx
mov fpacc.mantissa[2], dx
mov fpacc.mantissa[0], si
mov ax, fpop.Exponent ;FPACC assumes the same
mov fpacc.Exponent, ax ; exponent as FPOP.
AdjFPACCDone: jmp Adjusted
;
; If FPACC is so much smaller than FPOP that it is insignificant, set
; it to zero.
;
SetFPACC2Zero: xor ax, ax
mov fpacc.mantissa[0], ax
mov fpacc.mantissa[2], ax
mov fpacc.mantissa[4], ax
mov fpacc.mantissa[6], ax
mov fpacc.exponent, ax
mov fpacc.sign, al
;
; Now that the mantissas are aligned, let's add (or subtract) them.
;
Adjusted: mov al, fpacc.sign
xor al, fpop.sign
js SubEm
;
; If the signs are the same, simply add the mantissas together here.
;
mov ax, fpop.mantissa[0]
add fpacc.mantissa[0], ax
mov ax, fpop.mantissa[2]
adc fpacc.mantissa[2], ax
mov ax, fpop.mantissa[4]
adc fpacc.mantissa[4], ax
mov ax, fpop.mantissa[6]
adc fpacc.mantissa[6], ax
jnc Normalize
;
; If there was a carry out of the addition (quite possible since most
; fp values are normalized) then we need to shove the bit back into
; the number.
;
rcr fpacc.mantissa[6], 1
rcr fpacc.mantissa[4], 1
rcr fpacc.mantissa[2], 1
rcr fpacc.mantissa[0], 1
inc fpacc.exponent
;
; If there was a carry out of the bottom, add it back in (this rounds the
; result). No need to worry about a carry out of the H.O. bit this time--
; there is no way to add together two numbers to get a carry *and* all
; one bits in the result. Therefore, rounding at this point will not
; propagate all the way through.
;
adc fpacc.Mantissa [0], 0
jnc Normalize
inc fpacc.Mantissa [2]
jnz Normalize
inc fpacc.Mantissa [4]
jnz Normalize
inc fpacc.Mantissa [6]
jmp Normalize
;
;
;
; If the signs are different, we've got to deal with four possibilities:
;
; 1) fpacc is negative and its magnitude is greater than fpop's.
; Result is negative, fpacc.mant := fpacc.mant - fpop.mant.
;
; 2) fpacc is positive and its magnitude is greater than fpop's.
; Result is positive, fpacc.mant := fpacc.mant - fpop.mant.
;
; 3) fpacc is negative and its magnitude is less than fpop's.
; Result is positive, fpacc.mant := fpop.mant - fpacc.mant.
;
; 4) fpacc is positive and its magnitude is less than fpop's.
; Result is negative, fpacc.mant := fpop.mant - fpacc.mant.
;
SubEm: mov ax, fpacc.mantissa[0]
mov bx, fpacc.mantissa[2]
mov dx, fpacc.mantissa[4]
mov si, fpacc.mantissa[6]
sub ax, fpop.mantissa[0]
sbb bx, fpop.mantissa[2]
sbb dx, fpop.mantissa[4]
sbb si, fpop.mantissa[6]
jnc StoreFPACC
;
; Whoops! FPOP > FPACC, fix that down here.
;
not ax
not bx
not dx
not si
inc ax
jnz StoreFPACCSign
inc bx
jnz StoreFPAccSign
inc dx
jnz StoreFPAccSign
inc si
;
StoreFPAccSign: xor fpacc.sign, 80h ;Flip sign if case 3/4.
;
StoreFPAcc: mov fpacc.mantissa[0], ax
mov fpacc.mantissa[2], bx
mov fpacc.mantissa[4], dx
mov fpacc.mantissa[6], si
; Normalize the result down here. Start by shifting 16 bits at a time,
; then eight bits, then one bit at a time.
Normalize: mov ax, fpacc.Mantissa[0] ;First, see if the result
or ax, fpacc.Mantissa[2] ; is zero. Can't normalize
or ax, fpacc.Mantissa[4] ; if this is the case.
or ax, fpacc.Mantissa[6]
jnz NormLoop
mov fpacc.Exponent, ax ;Force everything to zero
mov fpacc.Sign, al ; if result is zero.
jmp Done
NormLoop: mov ax, fpacc.mantissa[6]
or ax, ax ;See if zero (which means we
jnz Try8Bits ; can shift 16 bits).
mov ax, fpacc.mantissa[4]
mov fpacc.mantissa[6], ax
mov ax, fpacc.mantissa[2]
mov fpacc.mantissa[4], ax
mov ax, fpacc.mantissa[0]
mov fpacc.mantissa[2], ax
mov fpacc.mantissa[0],0
sub fpacc.exponent, 16
jmp NormLoop
;
; Okay, see if we can normalize eight bits at a shot.
;
Try8Bits: mov al, byte ptr fpacc.mantissa[7]
cmp al, 0
jnz Try1Bit
mov ax, fpacc.mantissa[5]
mov fpacc.mantissa[6], ax
mov ax, fpacc.mantissa[3]
mov fpacc.mantissa[4], ax
mov ax, fpacc.mantissa[1]
mov fpacc.mantissa[3], ax
mov al, byte ptr fpacc.mantissa[0]
mov byte ptr fpacc.mantissa[1], al
mov byte ptr fpacc.mantissa[0], 0
sub fpacc.exponent, 8
;
Try1Bit: mov ax, fpacc.mantissa[6]
test ah, 80h
jnz Done
mov bx, fpacc.mantissa[4]
mov dx, fpacc.mantissa[2]
mov si, fpacc.mantissa[0]
OneBitLp: dec fpacc.exponent
shl si, 1
rcl dx, 1
rcl bx, 1
rcl ax, 1
or ax, ax ;See if bit 15 is set.
jns OneBitLp
mov fpacc.mantissa[6], ax
mov fpacc.mantissa[4], bx
mov fpacc.mantissa[2], dx
mov fpacc.mantissa[0], si
;
Done:
pop si
pop dx
pop cx
pop bx
pop ax
pop ds
ret
sl_fadd endp
;
;
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
; Floating point comparison.
;---------------------------------------------------------------------------
;
;
; FCMP
; Compares value in FPACC to value in FPOP.
; Returns -1 in AX if FPACC is less than FPOP,
; Returns 0 in AX if FPACC is equal to FPOP,
; Returns 1 in AX if FPACC is greater than FPOP.
;
; Also returns this status in the flags (by comparing AX against zero
; before returning) so you can use JE, JNE, JG, JGE, JL, or JLE after this
; routine to test the comparison.
;
public sl_fcmp
sl_fcmp proc far
assume ds:StdGrp
push ds
mov ax, StdGrp
mov ds, ax
;
; First compare the signs of the mantissas. If they are different, the
; negative one is smaller.
;
mov al, byte ptr FPACC+10 ;Get sign bit
xor al, byte ptr FPOP+10 ;See if the signs are different
jns SameSign
;
; If the signs are different, then the sign of FPACC determines the result
;
test byte ptr FPACC+10, 80h
jnz IsLT
jmp short IsGT
;
; Down here the signs are the same. First order of business is to compare
; the exponents. The one with the larger exponent wins. If the exponents
; are equal, then we need to compare the mantissas. If the mantissas are
; the same then the two numbers are equal. If the mantissas are different
; then the larger one wins. Note that this discussion is for positive values
; only, if the numbers are negative, then we must reverse the win/loss value
; (win=GT).
;
SameSign: mov ax, FPACC.exponent ;One thing cool about bias-
cmp ax, FPOP.exponent ; 1023 exponents is that we
ja MayBeGT ; can use an unsigned compare
jb MayBeLT
;
; If the exponents are equal, we need to start comparing the mantissas.
; This straight line code turns out to be about the fastest way to do it.
;
mov ax, word ptr FPACC.mantissa+6
cmp ax, word ptr FPOP.mantissa+6
ja MayBeGT
jb MayBeLT
mov ax, word ptr FPACC.mantissa+4
cmp ax, word ptr FPOP.mantissa+4
ja MayBeGT
jb MayBeLT
mov ax, word ptr FPACC.mantissa+2
cmp ax, word ptr FPOP.mantissa+2
ja MayBeGT
jb MayBeLT
mov ax, word ptr FPACC.mantissa
cmp ax, word ptr FPOP.mantissa
ja MayBeGT
je IsEq ;They're equal at this point.
;
; MayBeLT- Looks like less than so far, but we need to check the sign of the
; numbers, if they are negative then FPACC is really GT FPOP. Remember, the
; sign is not part of the mantissa!
;
MayBeLT: test FPACC.sign, 80h
js IsGT
;
IsLT: mov ax, -1
jmp short cmpRtn
;
; Same story here for MayBeGT
;
MayBeGT: test FPACC.sign, 80h
js IsLT
;
IsGT: mov ax, 1
jmp short cmpRtn
;
IsEq: xor ax, ax
cmpRtn: pop ds
cmp ax, 0 ;Set the flags as appropriate
ret
sl_fcmp endp
assume ds:nothing
;
;
;
;
;
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
; Floating Point Multiplication
;---------------------------------------------------------------------------
;
;
;
;
; sl_fmul- Multiplies facc by fop and leaves the result in facc.
;
public sl_fmul
sl_fmul proc far
assume ds:StdGrp
push ds
push ax
push bx
push cx
push dx
push si
push di
;
mov ax, StdGrp
mov ds, ax
;
; See if either operand is zero:
;
mov ax, fpacc.mantissa[0] ;No need to check exponent!
or ax, fpacc.mantissa[2]
or ax, fpacc.mantissa[4]
or ax, fpacc.mantissa[6]
jz ProdIsZero
;
mov ax, fpop.mantissa[0]
or ax, fpop.mantissa[2]
or ax, fpop.mantissa[4]
or ax, fpop.mantissa[6]
jnz ProdNotZero
;
ProdIsZero: xor ax, ax ;Need this!
mov fpacc.sign, al
mov fpacc.exponent, ax
mov fpacc.mantissa[0], ax
mov fpacc.mantissa[2], ax
mov fpacc.mantissa[4], ax
mov fpacc.mantissa[6], ax
jmp FMulDone
;
; If both operands are non-zero, compute the true product down here.
;
ProdNotZero: mov al, fpop.sign ;Compute the new sign.
xor fpacc.sign, al
;
; Eliminate bias in the exponents, add them, and check for 16-bit signed
; overflow.
;
mov ax, fpop.exponent ;Compute new exponent.
sub ax, 7fffh ;Subtract BIAS and adjust
mov bx, fpacc.Exponent
sub bx, 7fffh
add ax, bx ; for fractional multiply.
jno GoodExponent
;
; If the exponent overflowed, set up the overflow value here.
;
mov ax, 0ffffh
mov fpacc.exponent, ax ;Largest exponent value
mov fpacc.mantissa[0], ax ; and largest mantissa, too!
mov fpacc.mantissa[2], ax
mov fpacc.mantissa[4], ax
mov fpacc.mantissa[6], ax
jmp FMulDone
;
GoodExponent: add ax, 8000h ;Add the bias back in (note
mov fpacc.Exponent, ax ; Mul64 below causes shift
; ; to force bias of 7fffh.
; Okay, compute the product of the mantissas down here.
;
call Mul64
;
; Normalize the product. Note: we know the product is non-zero because
; both of the original operands were non-zero.
;
mov cx, fpacc.exponent
jmp short TestNrmMul
NrmMul1: sub cx, 16
mov ax, fprod[12]
mov fprod[14], ax
mov ax, fprod[10]
mov fprod[12], ax
mov ax, fprod[8]
mov fprod[10], ax
mov ax, fprod[6]
mov fprod[8], ax
mov ax, fprod[4]
mov fprod[6], ax
mov ax, fprod[2]
mov fprod[4], ax
mov ax, fprod[0]
mov fprod[2], ax
mov fprod[0], 0
TestNrmMul: cmp cx, 16
jb DoNrmMul8
mov ax, fprod[14]
or ax, ax
jz NrmMul1
;
; See if we can shift the product a whole byte
;
DoNrmMul8: cmp ah, 0 ;Contains fprod[15] from above.
jnz DoOneBits
cmp cx, 8
jb DoOneBits
mov ax, fprod[13]
mov fprod[14], ax
mov ax, fprod[11]
mov fprod[12], ax
mov ax, fprod[9]
mov fprod[10], ax
mov ax, fprod[7]
mov fprod[8], ax
mov ax, fprod[5]
mov fprod[6], ax
mov ax, fprod[3]
mov fprod[4], ax
mov ax, fprod[1]
mov fprod[2], ax
mov al, byte ptr fprod[0]
mov byte ptr fprod[1], al
mov byte ptr fprod[0], 0
sub cx, 8
;
DoOneBits: mov ax, fprod[14]
mov bx, fprod[12]
mov dx, fprod[10]
mov si, fprod[8]
mov di, fprod[6]
jmp short TestOneBits
;
OneBitLoop: shl fprod[0], 1
rcl fprod[2], 1
rcl fprod[4], 1
rcl di, 1
rcl si, 1
rcl dx, 1
rcl bx, 1
rcl ax, 1
dec cx
TestOneBits: jcxz StoreProd
test ah, 80h
jz OneBitLoop
;
StoreProd: mov fpacc.mantissa[6], ax
mov fpacc.mantissa[4], bx
mov fpacc.mantissa[2], dx
mov fpacc.mantissa[0], si
mov fpacc.exponent, cx
or ax, bx
or ax, dx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -