home *** CD-ROM | disk | FTP | other *** search
- ;*******************************************************************
- ; FLOATING POINT
- ; ADDITION AND SUBTRACTION
- ; ROUTINE
- ;*******************************************************************
- FLOAT_A PROC NEAR
- ;entry point for subtraction
- SUB_F: MOV BX,0080H ;set mask to reverse sign of operand2
- JMP SHORT F1 ;and go to main routine
- ;
- ;entry point for addition
- ADD_F: SUB BX,BX ;clear mask register BX
- ;
- ;get operand1 from address in DI
- F1: PUSH SI ;save index registers
- PUSH DI ;
- MOV DX,[DI]+2 ;exponent goes in DH--mantissa in DL
- MOV AX,[DI] ;and AX
-
- ;get operand2 from address in SI
- XOR BX,[SI]+2 ;exponent goes in BH--mantissa in BL
- MOV CX,[SI] ;and CX
-
- ;***************************************************
- ; Floating point addition routine begins here
- ; operands are in the following format:
- ; DH DL bit 7 DL AX
- ; Operand1 exponent sign mantissa
- ;
- ; BH BL bit 7 BL CX
- ; Operand2 exponent sign mantissa
- ;***************************************************
-
- ;save signs
- MOV SI,10000000B ;put mask for sign bit is SI
- MOV DI,SI ;and in DI
-
- AND SI,DX ;put sign of operand1 in SI bit 7
- AND DI,BX ;put sign of operand2 in DI bit 7
-
- CMP SI,DI ;
- JE A1 ;if signs are unequal
- ADD DI,8000H ;set bit 15 to 1. Bit 15 is
- ADD SI,8000H ;addition/subtraction flag
-
- A1: OR DL,10000000B ;restore leading ones
- OR BL,10000000B ;
- ;put smaller operand in DX:AX
- CMP DX,BX ;compare first word
- JA A2 ;exchange if DX:AX is larger
- JB A3 ;
-
- CMP AX,CX ;equal first words; compare second
- JA A2 ;
- JB A3 ;
- ;operands are equal
- OR DI,DI ;if signs are unequal
- JNS A3 ;
-
- SUB DX,DX ;set result in DX:AX to zero
- MOV AX,DX ;
- JMP EXIT ;and return
-
- A2: XCHG DX,BX ;exchange operands
- XCHG AX,CX ;
- MOV DI,SI ;put sign of larger in DI
-
- A3: MOV SI,CX ;larger operand is now in BX:SI
- ;compute exponent difference
- MOV CL,BH ;put larger exponent in CL
- SUB CL,DH ;and subtract the smaller exponent
-
- ;CL is COUNT of bits to shift DX:AX
- CMP CL,24 ;if COUNT > 24, smaller operand is
- JLE A4 ;effectively 0, so
- MOV DX,BX ;put larger operand(result) in DX:AX
- MOV AX,SI ;
- JMP FINISH ;and finish
- ;ALIGN fractions (shift smaller right)
- A4: SUB DH,DH ;clear DH
- MOV CH,DH ;clear CH
-
- A5: CMP CL,8 ;
- JL A6 ;if COUNT >= 8
- ;shift right in byte increments
- OR CH,DH ;put trailing bits in CH
- MOV DH,AL ;move leading bits in AL (and any
- ;others that happen to be set) to DH
- MOV AL,AH ;shift upper bytes right
- MOV AH,DL ;
- SUB DL,DL ;set leading byte to zero
- SUB CL,8 ;decrement COUNT
- JMP SHORT A5 ;if COUNT >= 8, repeat
-
- A6: OR CH,CH ;if any bits set in CH
- JZ A7 ;
- OR CH,80H ;set sticky bit
-
- A7: OR CL,CL ;
- JZ A9 ;if COUNT > 0
- ;shift right COUNT bits
- A8: SHR DL,1 ;rotate mantissa in DL:AX right
- RCR AX,1 ;
- RCR DH,1 ;rotate round bits in DH:CH right
- RCR CH,1 ;
- DEC CL ;decrement COUNT
- JNZ A8 ;repeat if COUNT in CL not zero
-
- MOV CL,3FH ;put mask in lower 6 bits of CL
- AND CL,DH ;pick up rounding bits from DH
- AND DH,0C0H ;zero out all but two guard bits in DH
- ;operands are now aligned
- A9: OR DI,DI ;if signs were the same,i.e., sign
- JS A10 ;bit = 0, then
-
- ADD AX,SI ;ADD the two operands
- ADC DL,BL ;
- JNC R0 ;if there was a carry, fraction is
- ;greater than 0, so normalize
- INC BH ;increment exponent
- JZ OVER_F ;jump if exponent overflow
- RCR DL,1 ;shift fraction right one bit
- RCR AX,1 ;
- RCR DH,1 ;
- JMP SHORT R0 ;
- ;SUBTRACT the two operands
- A10: XCHG SI,AX ;put larger operand in DL:AX
- XCHG DL,BL ;
- NEG DH ;subtract DH (guard bits)
- SBB AX,SI ;subtract significant portions
- SBB DL,BL ;
- JS R0 ;if DL bit 7 is 1, round
- ;NORMALIZE
- A11: DEC BH ;decrement exponent
- JZ UNDER_F ;jump if exponent underflow
- SHL DH,1 ;shift mantissa left
- RCL AX,1 ;
- RCL DL,1 ;
- OR DL,DL ;
- JNS A11 ;repeat if still not normalized
-
- RO: OR CH,CL ;set sticky bit before rounding
- JZ R1 ;if any trailing bits in CX
- OR DH,01000000B ;set sticky bit in DH
- ;ROUND normalized result
- R1: OR DH,DH ;if guard bit in DH is 0,
- JNS FINISH ;rounding is not necessary
- ;guard bit is on
- TEST AL,1 ;if fraction is odd, then
- JNZ R2 ;round it
-
- AND DH,7FH ;check trailing bits in DH and CX
- JZ FINISH ;if all zeros, rounding not needed
-
- R2: ADD AX,1 ;round by adding one
- ADC DL,0 ;
- JNC FINISH ;rounding may denormalize mantissa
-
- RCR DL,1 ;normalize by shifting right one
- RCR AX,1 ;
- INC BH ;increment exponent
- JZ OVER_F ;jump if exponent overflow
-
- FINISH: AND DL,7FH ;set sign bit to 0
- OR DX,DI ;restore sign from bit 7 of DI
- MOV DH,BH ;put exponent in DH
- SUB BX,BX ;set status=0 -- OK
- EXIT: POP DI ;restore index registers
- POP SI ;
- RET
-
- OVER_F: MOV DX,0FF7FH ;here for overflow--set result in DX:AX
- MOV AX,0FFFFH ;to maximum possible value with positive
- OR DX,DI ;sign. Restore actual result sign.
- MOV BX,1 ;set status=1 -- overflow
- JMP SHORT EXIT ;
- UNDER_F: SUB DX,DX ;set result in DX:AX to zero
- MOV AX,DX ;
- MOV BX,-1 ;set status=-1 -- underflow
- JMP SHORT EXIT ;
- FLOAT_A ENDP