home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / CLIBSRC3.ZIP / LDIVT.CAS < prev    next >
Encoding:
Text File  |  1992-06-10  |  3.9 KB  |  155 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - ldivt.cas
  3.  *
  4.  * function(s)
  5.  *        ldiv - long integer division
  6.  *-----------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1987, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #pragma inline
  18. #include <asmrules.h>
  19. #include <stdlib.h>
  20.  
  21.  
  22. /*-----------------------------------------------------------------------*
  23.  
  24. Name            ldiv - long integer division
  25.  
  26. Usage           ldiv_t ldiv(long numer, long denom);
  27.  
  28. Prototype in    stdlib.h
  29.  
  30. Description     ldiv computes  the quotient and remainder  of the ldivision
  31.                 of the numerator "numer" by the denominator "denom". If the
  32.                 result cannot be represented, the behavior is undefined.
  33.  
  34. Return value    ldiv returns  a structure of  type ldiv_t, comprising  both
  35.                 the quotient and the remainder.
  36.  
  37. *------------------------------------------------------------------------*/
  38. ldiv_t  _FARFUNC ldiv(long numer, long denom)
  39. {
  40.         ldiv_t  ldivR;
  41.  
  42. /*      Save frame pointer      */
  43.  
  44. asm     push    bp
  45. asm     xor     cx, cx
  46.  
  47. /*      Get both operands       */
  48.  
  49. asm     mov     ax, W0(numer)
  50. asm     mov     dx, W1(numer)
  51. asm     mov     bx, W0(denom)
  52. asm     mov     bp, W1(denom)
  53.  
  54. /*      Zero low word of high 32 bits of 64-bit remainder       */
  55.  
  56. asm     xor     si, si
  57.  
  58. /* Signed division should be done. Convert negative values to positive
  59.    and  do an  unsigned division.  Store the  sign value  in the  next
  60.    higher bit of cl  (test mask of 4). Thus when we  are done, testing
  61.    that bit will determine the sign of the result.
  62. */
  63.  
  64. /*     Negate numerator if negative number      */
  65.  
  66. asm     or      dx, dx
  67. asm     jns     PosNumer
  68. asm     neg     dx
  69. asm     neg     ax
  70. asm     sbb     dx, si
  71. asm     inc     cl
  72.  
  73. PosNumer:
  74.  
  75. /*      Negate denominator if negative number   */
  76.  
  77. asm     or      bp, bp
  78. asm     jns     PosDenom
  79. asm     neg     bp
  80. asm     neg     bx
  81. asm     sbb     bp, si
  82. asm     xor     cl, 1
  83.  
  84. PosDenom:
  85.  
  86. /*      Save sign of the result         */
  87.  
  88. asm     push    cx
  89.  
  90. /*      Use machine divide if high words are both zero  */
  91.  
  92. asm     mov     di, bp
  93. asm     or      di, dx
  94. asm     jnz     noQuickDiv
  95. asm     div     bx
  96. asm     xchg    si, dx
  97. asm     jmp     short commonOut
  98.  
  99. /*      Unsigned long division  */
  100.  
  101. noQuickDiv:
  102.  
  103. asm     mov     cx, 32          /* Shift counter */
  104. asm     mov     di, si          /* Fake a 64 bit dividend (clear high word) */
  105.  
  106. xLoop:
  107.  
  108. asm     shl     ax, 1           /* Shift dividend left one bit */
  109. asm     rcl     dx, 1
  110. asm     rcl     si, 1
  111. asm     rcl     di, 1
  112. asm     cmp     di, bp          /* Dividend larger? */
  113. asm     jb      noSub
  114. asm     ja      Subtract
  115. asm     cmp     si, bx          /* Maybe */
  116. asm     jb      noSub
  117.  
  118. Subtract:
  119.  
  120. asm     sub     si, bx
  121. asm     sbb     di, bp          /* Subtract the divisor */
  122. asm     inc     ax              /* build quotient */
  123. noSub:
  124. asm     loop    xLoop
  125.  
  126. /*      When done with the loop the four register value look like:
  127.  
  128.         |     di     |     si     |     dx     |     ax     |
  129.         |        remainder        |         quotient        |
  130. */
  131.  
  132. commonOut:
  133.  
  134. asm     pop     cx              /* Restore sign of the result */
  135. asm     jcxz    Divided
  136. asm     neg     di
  137. asm     neg     si
  138. asm     sbb     di, 0           /* Negate remainder */
  139. asm     neg     dx
  140. asm     neg     ax
  141. asm     sbb     dx, 0           /* Negate quotient */
  142.  
  143. /*      Restore frame pointer, and set ldiv_t structure         */
  144.  
  145. Divided:
  146.  
  147. asm     pop     bp
  148. asm     mov     W0(ldivR), ax
  149. asm     mov     W1(ldivR), dx
  150. asm     mov     W0(ldivR+4), si
  151. asm     mov     W1(ldivR+4), di
  152.  
  153.         return ldivR;
  154. }
  155.