home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / LDIVT.CAS < prev    next >
Encoding:
Text File  |  1990-06-07  |  4.3 KB  |  156 lines

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