home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / H_LDIV.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-06-07  |  4.4 KB  |  196 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      H_LDIV.ASM -- long division routine                          |
  3. ;|                                                                   |
  4. ;|      Turbo-C Run Time Library        Version 3.0                  |
  5. ;|                                                                   |
  6. ;|      Copyright (c) 1987,1988,1990 by Borland International Inc.   |
  7. ;|      All Rights Reserved.                                         |
  8. ;[]-----------------------------------------------------------------[]
  9.  
  10.     INCLUDE    RULES.ASI
  11.  
  12. _TEXT    segment    public byte 'CODE'
  13.     assume    cs:_TEXT
  14.     public    LDIV@
  15.     public    F_LDIV@
  16.         public  N_LDIV@
  17.     public    LUDIV@
  18.     public    F_LUDIV@
  19.         public  N_LUDIV@
  20.     public    LMOD@
  21.     public    F_LMOD@
  22.         public  N_LMOD@
  23.     public    LUMOD@
  24.     public    F_LUMOD@
  25.         public  N_LUMOD@
  26.  
  27. N_LDIV@:
  28.         pop     cx                      ;fix up far return
  29.         push    cs
  30.         push    cx
  31. LDIV@:
  32. F_LDIV@:
  33.     xor    cx,cx            ; signed divide
  34.     jmp    short common
  35.  
  36. N_LUDIV@:
  37.         pop     cx                      ;fix up far return
  38.         push    cs
  39.         push    cx
  40. LUDIV@:
  41. F_LUDIV@:
  42.     mov    cx,1            ; unsigned divide
  43.     jmp    short common
  44.  
  45. N_LMOD@:
  46.         pop     cx                      ;fix up far return
  47.         push    cs
  48.         push    cx
  49. LMOD@:
  50. F_LMOD@:
  51.     mov    cx,2            ; signed remainder
  52.     jmp    short    common
  53.  
  54. N_LUMOD@:
  55.         pop     cx                      ;fix up far return
  56.         push    cs
  57.         push    cx
  58. LUMOD@:
  59. F_LUMOD@:
  60.     mov    cx,3            ; unsigned remainder
  61.  
  62. ;
  63. ;    di now contains a two bit control value.  The low order
  64. ;    bit (test mask of 1) is on if the operation is unsigned,
  65. ;    signed otherwise.  The next bit (test mask of 2) is on if
  66. ;    the operation returns the remainder, quotient otherwise.
  67. ;
  68. common:
  69.     push    bp
  70.     push    si
  71.     push    di
  72.     mov    bp,sp            ; set up frame
  73.     mov    di,cx
  74. ;
  75. ;    dividend is pushed last, therefore the first in the args
  76. ;    divisor next.
  77. ;
  78.     mov    ax,10[bp]        ; get the first low word
  79.     mov    dx,12[bp]        ; get the first high word
  80.     mov    bx,14[bp]        ; get the second low word
  81.     mov    cx,16[bp]        ; get the second high word
  82.  
  83.     or    cx,cx
  84.     jnz    slow@ldiv        ; both high words are zero
  85.  
  86.     or    dx,dx
  87.     jz    quick@ldiv
  88.  
  89.     or    bx,bx
  90.     jz    quick@ldiv        ; if cx:bx == 0 force a zero divide
  91.                     ; we don't expect this to actually
  92.                     ; work
  93.  
  94. slow@ldiv:
  95.  
  96.     test    di,1            ; signed divide?
  97.     jnz    positive        ; no: skip
  98. ;
  99. ;        Signed division should be done.  Convert negative
  100. ;        values to positive and do an unsigned division.
  101. ;        Store the sign value in the next higher bit of
  102. ;        di (test mask of 4).  Thus when we are done, testing
  103. ;        that bit will determine the sign of the result.
  104. ;
  105.     or    dx,dx            ; test sign of dividend
  106.     jns    onepos
  107.     neg    dx
  108.     neg    ax
  109.     sbb    dx,0            ; negate dividend
  110.     or    di,0Ch
  111. onepos:
  112.     or    cx,cx            ; test sign of divisor
  113.     jns    positive
  114.     neg    cx
  115.     neg    bx
  116.     sbb    cx,0            ; negate divisor
  117.     xor    di,4
  118. positive:
  119.     mov    bp,cx
  120.     mov    cx,32            ; shift counter
  121.     push    di            ; save the flags
  122. ;
  123. ;    Now the stack looks something like this:
  124. ;
  125. ;        16[bp]: divisor (high word)
  126. ;        14[bp]: divisor (low word)
  127. ;        12[bp]: dividend (high word)
  128. ;        10[bp]: dividend (low word)
  129. ;         8[bp]: return CS
  130. ;         6[bp]: return IP
  131. ;         4[bp]: previous BP
  132. ;         2[bp]: previous SI
  133. ;          [bp]: previous DI
  134. ;        -2[bp]: control bits
  135. ;            01 - Unsigned divide
  136. ;            02 - Remainder wanted
  137. ;            04 - Negative quotient
  138. ;            08 - Negative remainder
  139. ;
  140.     xor    di,di            ; fake a 64 bit dividend
  141.     xor    si,si            ;
  142. xloop:
  143.     shl    ax,1            ; shift dividend left one bit
  144.     rcl    dx,1
  145.     rcl    si,1
  146.     rcl    di,1
  147.     cmp    di,bp            ; dividend larger?
  148.     jb    nosub
  149.     ja    subtract
  150.     cmp    si,bx            ; maybe
  151.     jb    nosub
  152. subtract:
  153.     sub    si,bx
  154.     sbb    di,bp            ; subtract the divisor
  155.     inc    ax            ; build quotient
  156. nosub:
  157.     loop    xloop
  158. ;
  159. ;    When done with the loop the four register value look like:
  160. ;
  161. ;    |     di     |     si     |     dx     |     ax     |
  162. ;    |        remainder        |         quotient        |
  163. ;
  164.     pop    bx            ; get control bits
  165.     test    bx,2            ; remainder?
  166.     jz    usequo
  167.     mov    ax,si
  168.     mov    dx,di            ; use remainder
  169.     shr    bx,1            ; shift in the remainder sign bit
  170. usequo:
  171.     test    bx,4            ; needs negative
  172.     jz    finish
  173.     neg    dx
  174.     neg    ax
  175.     sbb    dx,0            ; negate
  176. finish:
  177.     pop    di
  178.     pop    si
  179.     pop    bp
  180.     retf    8
  181.  
  182. quick@ldiv:
  183.     div    bx            ; unsigned divide
  184.                     ; DX = remainder AX = quotient
  185.         test    di,2            ; want remainder?
  186.     jz    quick@quo
  187.         xchg    ax,dx
  188.  
  189. quick@quo:
  190.  
  191.     xor    dx,dx
  192.         jmp     short finish
  193.  
  194. _TEXT    ends
  195.     end
  196.