?
Der Code dividiert zwei Zahlen und gibt das Ergebnis sowie den Rest aus.
Die Zahlen sind vom Typ "CLINT":
typedef unsigned short clint;
typedef clint CLINT[267];
Das C-Interface ist also:
void div_l(CLINT d1_l, CLINT d2_l, CLINT quot_l, CLINT rest_l);
Die ASN-Version geht nach der cdecl Aufrufkonvention.
C-Version:
div_l (CLINT d1_l, CLINT d2_l, CLINT quot_l, CLINT rest_l)
{
register clint *rptr_l, *bptr_l;
CLINT b_l;
clint r_l[2 + (CLINTMAXDIGIT << 1)]; /* Erlaube doppelt langen Rest + 1 Stelle */
clint *qptr_l, *msdptrb_l, *msdptrr_l, *lsdptrr_l;
USHORT bv, rv, qdach, ri, ri_1, ri_2, bn, bn_1;
ULONG right, left, rdach, borrow, carry, sbitsminusd;
unsigned int d = 0;
int i;
cpy_l (r_l, d1_l);
cpy_l (b_l, d2_l);
if (EQZ_L (b_l))
{
PURGEVARS_L ((1, sizeof (r_l), r_l));
ISPURGED_L ((1, sizeof (r_l), r_l));
return E_CLINT_DBZ; /* Division durch Null */
}
if (EQZ_L (r_l))
{
SETZERO_L (quot_l);
SETZERO_L (rest_l);
PURGEVARS_L ((1, sizeof (b_l), b_l));
ISPURGED_L ((1, sizeof (b_l), b_l));
return E_CLINT_OK;
}
i = cmp_l (r_l, b_l);
if (i == -1)
{
cpy_l (rest_l, r_l);
SETZERO_L (quot_l);
PURGEVARS_L ((2, sizeof (b_l), b_l,
sizeof (r_l), r_l));
ISPURGED_L ((2, sizeof (b_l), b_l,
sizeof (r_l), r_l));
return E_CLINT_OK;
}
else if (i == 0)
{
SETONE_L (quot_l);
SETZERO_L (rest_l);
PURGEVARS_L ((2, sizeof (b_l), b_l,
sizeof (r_l), r_l));
ISPURGED_L ((2, sizeof (b_l), b_l,
sizeof (r_l), r_l));
return E_CLINT_OK;
}
if (DIGITS_L (b_l) == 1)
{
goto shortdiv;
}
/* Schritt 1 */
msdptrb_l = MSDPTR_L (b_l);
bn = *msdptrb_l;
while (bn < BASEDIV2)
{
d++;
bn <<= 1;
}
sbitsminusd = (int)BITPERDGT - d;
if (d > 0)
{
bn += *(msdptrb_l - 1) >> sbitsminusd;
if (DIGITS_L (b_l) > 2)
{
bn_1 = (USHORT)((*(msdptrb_l - 1) << d) + (*(msdptrb_l - 2) >> sbitsminusd));
}
else
{
bn_1 = (USHORT)(*(msdptrb_l - 1) << d);
}
}
else
{
bn_1 = (USHORT)(*(msdptrb_l - 1));
}
/* Schritte 2 und 3 */
msdptrr_l = MSDPTR_L (r_l) + 1;
lsdptrr_l = MSDPTR_L (r_l) - DIGITS_L (b_l) + 1;
*msdptrr_l = 0;
qptr_l = quot_l + DIGITS_L (r_l) - DIGITS_L (b_l) + 1;
/* Schritt 4 */
while (lsdptrr_l >= LSDPTR_L (r_l))
{
ri = (USHORT)((*msdptrr_l << d) + (*(msdptrr_l - 1) >> sbitsminusd));
ri_1 = (USHORT)((*(msdptrr_l - 1) << d) + (*(msdptrr_l - 2) >> sbitsminusd));
if (msdptrr_l - 3 > r_l)
{
ri_2 = (USHORT)((*(msdptrr_l - 2) << d) + (*(msdptrr_l - 3) >> sbitsminusd));
}
else
{
ri_2 = (USHORT)(*(msdptrr_l - 2) << d);
}
if (ri != bn) /* fast immer */
{
qdach = (USHORT)((rdach = ((ULONG)ri << BITPERDGT) + (ULONG)ri_1) / bn);
right = ((rdach = (rdach - (ULONG)bn * qdach)) << BITPERDGT) + ri_2;
/* test qdach */
if ((left = (ULONG)bn_1 * qdach) > right)
{
qdach--;
if ((rdach + bn) < BASE)
/* sonst bn_1 * qdach < rdach * b_l */
{
if ((left - bn_1) > (right + ((ULONG)bn << BITPERDGT)))
{
qdach--;
}
}
}
}
else /* ri == bn, seltenerer Fall */
{
qdach = BASEMINONE;
right = ((ULONG)(rdach = (ULONG)bn + (ULONG)ri_1) << BITPERDGT) + ri_2;
if (rdach < BASE) /* sonst ist bn_1 * qdach < rdach * b_l */
{
/* test qdach */
if ((left = (ULONG)bn_1 * qdach) > right)
{
qdach--;
if ((rdach + bn) < BASE)
/* sonst ist bn_1 * qdach < rdach * b_l */
{
if ((left - bn_1) > (right + ((ULONG)bn << BITPERDGT)))
{
qdach--;
}
}
}
}
}
/* Schritt 5 */
borrow = BASE;
carry = 0;
for (bptr_l = LSDPTR_L (b_l), rptr_l = lsdptrr_l; bptr_l <= msdptrb_l; bptr_l++, rptr_l++)
{
if (borrow >= BASE)
{
*rptr_l = (USHORT)(borrow = ((ULONG)(*rptr_l) + BASE -
(ULONG)(USHORT)(carry = (ULONG)(*bptr_l) *
qdach + (ULONG)(USHORT)(carry >> BITPERDGT))));
}
else
{
*rptr_l = (USHORT)(borrow = ((ULONG)(*rptr_l) + BASEMINONEL -
(ULONG)(USHORT)(carry = (ULONG)(*bptr_l) *
qdach + (ULONG)(USHORT)(carry >> BITPERDGT))));
}
}
if (borrow >= BASE)
{
*rptr_l = (USHORT)(borrow = ((ULONG)(*rptr_l) + BASE -
(ULONG)(USHORT)(carry >> BITPERDGT)));
}
else
{
*rptr_l = (USHORT)(borrow = ((ULONG)(*rptr_l) + BASEMINONEL -
(ULONG)(USHORT)(carry >> BITPERDGT)));
}
/* Schritt 6 */
*qptr_l = qdach;
if (borrow < BASE)
{
carry = 0;
for (bptr_l = LSDPTR_L (b_l), rptr_l = lsdptrr_l; bptr_l <= msdptrb_l; bptr_l++, rptr_l++)
{
*rptr_l = (USHORT)(carry = ((ULONG)(*rptr_l) + (ULONG)(*bptr_l) +
(ULONG)(USHORT)(carry >> BITPERDGT)));
}
*rptr_l += (USHORT)(carry >> BITPERDGT);
(*qptr_l)--;
}
/* Schritt 7 */
msdptrr_l--;
lsdptrr_l--;
qptr_l--;
}
/* Schritt 8 */
SETDIGITS_L (quot_l, DIGITS_L (r_l) - DIGITS_L (b_l) + 1);
RMLDZRS_L (quot_l);
SETDIGITS_L (r_l, DIGITS_L (b_l));
cpy_l (rest_l, r_l);
return;
/* Kurze Division */
shortdiv:
rv = 0;
bv = *LSDPTR_L (b_l);
for (rptr_l = MSDPTR_L (r_l), qptr_l = quot_l + DIGITS_L (r_l); rptr_l >= LSDPTR_L (r_l); rptr_l--, qptr_l--)
{
*qptr_l = (USHORT)((rdach = ((((ULONG)rv) << BITPERDGT) +
(ULONG)*rptr_l)) / bv);
rv = (USHORT)(rdach - (ULONG)bv * (ULONG)*qptr_l);
}
SETDIGITS_L (quot_l, DIGITS_L (r_l));
RMLDZRS_L (quot_l);
u2clint_l (rest_l, rv);
}