home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
TPL60N19
/
ARISOURC
/
LONGDIV.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-25
|
6KB
|
124 lines
; *******************************************************
; * *
; * Turbo Pascal Runtime Library Version 6.0 *
; * Longint Division *
; * *
; * Copyright (C) 1989-1993 Norbert Juffa *
; * *
; *******************************************************
TITLE LONGDIV
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE
; Externals
EXTRN HaltError:NEAR
; Publics
PUBLIC LongDiv
;-------------------------------------------------------------------------------
; LongDiv divides two LONGINT numbers, the dividend and the divisor, resulting
; in a quotient and a remainder. The routine checks for an attempted division
; by zero. In that case, it returns to the error handler with error code C8h.
;
; INPUT: DX:AX dividend
; BX:CX divisor
;
; OUTPUT: DX:AX quotient of division of dividend by divisor
; BX:CX remainder of division of dividend by divisor
;
; DESTROYS: AX,BX,CX,DX,SI,DI,Flags
;-------------------------------------------------------------------------------
LongDiv PROC FAR
XOR DX, BX ; SF set if quotient negative
PUSHF ; save flag
XOR DX, BX ; dividend negative ?
PUSHF ; SF set if dividend (&remaindr) negative
JNS $dividnd_pos ; no, ->
NOT DX ; negate
NEG AX ; dividend
SBB DX, -1 ; in DX:AX
$dividnd_pos:OR BX, BX ; divisor negative ?
JNS $divisor_pos ; no, ->
NOT BX ; negate
NEG CX ; divisor
SBB BX, -1 ; in BX:CX
$divisor_pos:JNZ $big_divisor ; divisor > 65535
CMP DX, CX ; only one division needed ?
JB $one_div ; yes, one division sufficient
JCXZ $zero_divide ; divisor is zero, error
DB 087h, 0C3h ; XCHG AX, BX ; save lo-word of dividend in BX
XCHG AX, DX ; get hi-word of dividend, load DX with 0
DIV CX ; hi-word of quotient in AX
XCHG AX, BX ; BX = quot. hi-word, AX = divid. lo-word
$one_div: DIV CX ; AX = quotient lo-word
MOV CX, DX ; CX = remainder lo-word,
MOV DX, BX ; DX = quotient hi-word
XOR BX, BX ; clear remainder hi-word (rem. in BX:CX)
JMP $set_sign ; make signed
$big_divisor:PUSH DX ; save
PUSH AX ; dividend
MOV SI, CX ; save
MOV DI, BX ; divisor
OR BH, BH ; shift more than 8 bits ?
JZ $scale_down ; no, do bit shifts
MOV CL, CH ; shift
MOV CH, BL ; divisor
MOV BL, BH ; and
XOR BH, BH ; dividend
MOV AL, AH ; 8 bits
MOV AH, DL ; right
MOV DL, DH ; each
MOV DH, BH ;
$scale_down: SHR DX, 1 ; scale
RCR AX, 1 ; divisor
SHR BX, 1 ; and
RCR CX, 1 ; dividend until
JNZ $scale_down ; divisor < 65536
DIV CX ; compute quotient
MOV CX, AX ; save quotient
MOV BX, AX ; save quotient
MUL DI ; quotient * divisor hi-word
XCHG AX, CX ; save result in CX, get quotient from AX
MUL SI ; quotient * divisor lo-word
ADD DX, CX ; DX:AX = quotient * divisor
POP CX ; get dividend lo-word
SUB CX, AX ; divid. lo-word - (quot.*divisor)lo-word
MOV AX, BX ; get quotient
POP BX ; restore dividend hi-word
SBB BX, DX ; subtract divisor * quot. from dividend
JNB $remaindr_ok ; ok if remainder > 0
ADD CX, SI ; compute
ADC BX, DI ; correct remaindr (0.095% of all cases)
DEC AX ; adjust quotient
$remaindr_ok:XOR DX, DX ; clear hi-word of quotient (AX ≤ 7FFFh)
$set_sign: POPF ; remainder negative ?
JNS $pos_remaind ; no, ->
NOT BX ; negate
NEG CX ; remainder
SBB BX, -1 ; in BX:CX
$pos_remaind:POPF ; result negative ?
JNS $pos_result ; no, ->
NOT DX ; negate
NEG AX ; quotient
SBB DX, -1 ; in DX:AX
$pos_result: RET ; done, return & pop arguments
$zero_divide:ADD SP, 4 ; remove saved flags from stack
MOV AX, 0C8H ; load error code 200, "division by zero"
JMP HaltError ; execute error handler
LongDiv ENDP
ALIGN 4
CODE ENDS
END