Category : Assembly Language Source Code
Archive   : MATHASM.ZIP
Filename : FLOAT.ASM

 
Output of file : FLOAT.ASM contained in archive : MATHASM.ZIP
;*******************************************************************
; 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

  3 Responses to “Category : Assembly Language Source Code
Archive   : MATHASM.ZIP
Filename : FLOAT.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/