1 ;[]-----------------------------------------------------------------[]
\r
2 ;| H_LDIV.ASM -- long division routine |
\r
4 ;| C/C++ Run Time Library Version 4.0 |
\r
6 ;| Copyright (c) 1987, 1991 by Borland International Inc. |
\r
7 ;| All Rights Reserved. |
\r
8 ;[]-----------------------------------------------------------------[]
\r
11 .386C ;JAB - we use 386 instructions
\r
13 _TEXT segment public byte 'CODE'
\r
29 pop cx ;fix up far return
\r
34 xor cx,cx ; signed divide
\r
39 ; If we're using a 386 or better, the two instructions above get patched
\r
40 ; to be NOP's (4 of them). So, instead of using the looping code,
\r
41 ; we use the 386's long divide instruction.
\r
43 ; The stack after setting up the stack frame:
\r
44 ; 12[bp]: divisor (high word)
\r
45 ; 10[bp]: divisor (low word)
\r
46 ; 8[bp]: dividend (high word)
\r
47 ; 6[bp]: dividend (low word)
\r
50 ; 0[bp]: previous BP
\r
55 mov bp,sp ;Save BP, and set it equal to stack
\r
57 mov eax,[DWORD PTR bp+6]
\r
59 idiv [DWORD PTR bp+10]
\r
64 retf 8 ;Return to original caller
\r
69 pop cx ;fix up far return
\r
74 mov cx,1 ; unsigned divide
\r
78 pop cx ;fix up far return
\r
83 mov cx,2 ; signed remainder
\r
87 pop cx ;fix up far return
\r
92 mov cx,3 ; unsigned remainder
\r
95 ; di now contains a two bit control value. The low order
\r
96 ; bit (test mask of 1) is on if the operation is unsigned,
\r
97 ; signed otherwise. The next bit (test mask of 2) is on if
\r
98 ; the operation returns the remainder, quotient otherwise.
\r
104 mov bp,sp ; set up frame
\r
107 ; dividend is pushed last, therefore the first in the args
\r
110 mov ax,10[bp] ; get the first low word
\r
111 mov dx,12[bp] ; get the first high word
\r
112 mov bx,14[bp] ; get the second low word
\r
113 mov cx,16[bp] ; get the second high word
\r
116 jnz slow@ldiv ; both high words are zero
\r
122 jz quick@ldiv ; if cx:bx == 0 force a zero divide
\r
123 ; we don't expect this to actually
\r
128 test di,1 ; signed divide?
\r
129 jnz positive ; no: skip
\r
131 ; Signed division should be done. Convert negative
\r
132 ; values to positive and do an unsigned division.
\r
133 ; Store the sign value in the next higher bit of
\r
134 ; di (test mask of 4). Thus when we are done, testing
\r
135 ; that bit will determine the sign of the result.
\r
137 or dx,dx ; test sign of dividend
\r
141 sbb dx,0 ; negate dividend
\r
144 or cx,cx ; test sign of divisor
\r
148 sbb cx,0 ; negate divisor
\r
152 mov cx,32 ; shift counter
\r
153 push di ; save the flags
\r
155 ; Now the stack looks something like this:
\r
157 ; 16[bp]: divisor (high word)
\r
158 ; 14[bp]: divisor (low word)
\r
159 ; 12[bp]: dividend (high word)
\r
160 ; 10[bp]: dividend (low word)
\r
163 ; 4[bp]: previous BP
\r
164 ; 2[bp]: previous SI
\r
165 ; [bp]: previous DI
\r
166 ; -2[bp]: control bits
\r
167 ; 01 - Unsigned divide
\r
168 ; 02 - Remainder wanted
\r
169 ; 04 - Negative quotient
\r
170 ; 08 - Negative remainder
\r
172 xor di,di ; fake a 64 bit dividend
\r
175 shl ax,1 ; shift dividend left one bit
\r
179 cmp di,bp ; dividend larger?
\r
186 sbb di,bp ; subtract the divisor
\r
187 inc ax ; build quotient
\r
191 ; When done with the loop the four register value look like:
\r
193 ; | di | si | dx | ax |
\r
194 ; | remainder | quotient |
\r
196 pop bx ; get control bits
\r
197 test bx,2 ; remainder?
\r
200 mov dx,di ; use remainder
\r
201 shr bx,1 ; shift in the remainder sign bit
\r
203 test bx,4 ; needs negative
\r
215 div bx ; unsigned divide
\r
216 ; DX = remainder AX = quotient
\r
217 test di,2 ; want remainder?
\r