home *** CD-ROM | disk | FTP | other *** search
- ;*************************************************************
- ; FLOATING POINT
- ; DIVISION ROUTINE
- ;*************************************************************
- DIV_F PROC NEAR
- PUSH SI ;save index registers
- PUSH DI
- ; divide by zero?
- MOV DX,[SI] ;get op2 (divisor) in CX:DX
- MOV CX,[SI]+2
- MOV BX,10 ;set error flag
- MOV AX,DX ;is op2 zero?
- OR AX,CX
- JNZ D1 ;if zero, quit with BX=10
- JMP EXIT
- ; compute result sign
- D1: MOV AL,CL ;OP1 high byte in AL
- XOR AL,[DI]+2 ;XOR with OP2 high byte
- AND AX,0080H ;isolate sign bit
- PUSH AX ;save it
- ; compute exponent
- SUB AX,AX
- MOV BX,AX
- MOV AL,CH ;E2 in AX
- MOV BL,[DI]+3 ;E1 in BX
- SUB AX,128 ;remove bias
- SUB BX,AX ;E1-E2
- INC BX ;add 1 since shift right later
- ;
- CMP BX,255 ;overflow if
- JLE D3 ;E>255
- JMP D13
- ;
- D3: CMP BX,0 ;underflow if
- JGE D5 ;E<0
- JMP D14
- ; compute 1-(OP2LO/OP2HI)/2^16
- D5: PUSH BX ;save E in BL
- SUB AX,AX
- MOV BH,CL ;OP2HI in BX
- MOV BL,DH
- OR BH,10000000B ;restore leading 1
- MOV DH,DL ;OP2LO in DX
- MOV DL,AL
- OR DX,DX ;if OP2LO is zero
- JNZ D6
- XCHG BX,AX ;put OP2HI in AX
- MOV SI,BX ;set result in BX:SI to zero
- JMP SHORT D8 ;and skip this step
- ; compute OP2LO/OP2HI first
- D6: SUB CX,CX
- CMP DX,BX ;if OP2LO>=OP2HI, quotient>=1
- JB D7
- SUB DX,BX ;subtract OP2HI to prevent overflow
- MOV CX,1 ;save quotient 1 or 0 in CX
- ;
- D7: DIV BX ;OP2LO/OP2HI now in CX:AX
- ;
- PUSH CX ;save OP2LO/OP2HI
- PUSH AX
- SUB AX,AX ;divide remainder in DX:AX
- DIV BX
- POP DX
- POP CX ;OP2LO/OP2HI in CX:DX:AX
- ; subtract it from 1
- PUSH DI ;save DI & OP2HI
- PUSH BX
- SUB DI,DI ;clear registers
- MOV SI,DI
- MOV BX,DI
- SUB DI,AX
- SBB SI,DX
- SBB BX,CX
- POP AX ;retrieve OP2HI & DI
- POP DI
- ; compute OP1/OP2HI
- D8: PUSH BX ;save 1-OP1LO/OP2HI
- PUSH SI
- MOV BX,AX ;OP2HI in BX
- SUB AX,AX ;clear AX & SI
- MOV SI,AX
- MOV DX,[DI]+1 ;OP1 in DX:AX
- OR DH,10000000B ;restore leading 1
- MOV AH,[DI]
- ;
- CMP DX,BX ;if OP1>=OP2HI
- JB D9
- SUB DX,BX ;subtract OP2HI to prevent overflow
- INC SI ;and save quotient of one in SI
- ;
- D9: DIV BX ;divide OP1/OP2HI
- MOV CX,AX ;save quotient in CX
- SUB AX,AX
- DIV BX ;divide remainder in DX
- MOV DX,CX ;OP1/OP2HI now in SI:DX:AX
- SHR SI,1 ;shift it right
- RCR DX,1
- RCR AX,1 ;now in DX:AX
- ; compute (OP1/OP2HI)*(OP2LO/OP2HI)/2^16
- POP BX ;1-OP2LO/OP2H9)/2^16 in CX:BX
- POP CX
- MOV SI,BX ;if OP2LP/OP2HI was zero
- OR SI,CX ;product is OP1/OP2HI
- JZ D10 ;so no need to multiply
- CALL MUL32 ;do the multiplication
- ; normalize
- D10: POP BX ;get exponent in BX
- D11: OR DX,DX
- JS D12 ;if sign bit off
- SHL CX,1 ;shift it left
- RCL AX,1
- RCL DX,1
- DEC BX ;decrement exponent
- JMP D11 ;see if normalized
- ; reformat for output
- D12: MOV BH,BL ;exponent in BH
- XCHG AH,AL ;move trailing bits up to DH
- XCHG DL,AH ;4 byte mantissa in DL:AX:DH
- XCHG DH,DL
- SUB CX,CX
- POP DI ;result sign in DI
- JMP R0 ;ROUND in addition routine
- ;
- D13: POP DI ;get sign in DI
- JMP OVER_F
- D14: POP AX ;remove sign from stack
- JMP UNDER_F
- DIV_F ENDP