home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CASM.ARJ / LMATH.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-07-27  |  3.0 KB  |  181 lines

  1. ;_ lmath.asm   Thu Apr 21 1988   Modified by: Walter Bright */
  2. ; Copyright (C) 1984-1988 by Northwest Software
  3. ; All Rights Reserved
  4. ; Written by Walter Bright
  5.  
  6. include    macros.asm
  7.  
  8.     begcode    lmath
  9.  
  10.     c_public _LMUL@,_LDIV@,_ULDIV@,_LCMP@
  11.  
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13. ; Multiply:
  14. ;    DX,AX = DX,AX * CX,BX
  15. ; CX is destroyed
  16.  
  17. func    _LMUL@
  18.     push    SI
  19.     mov    SI,DX        ;SI = d
  20.     xchg    AX,CX        ;AX = c, CX = a
  21.     tst    AX
  22.     jz    M1
  23.     mul    CX        ;AX = acl
  24. M1:    xchg    AX,SI        ;SI = acl, AX = d
  25.     tst    AX
  26.     jz    M2
  27.     mul    BX        ;AX = bdl
  28.     add    SI,AX        ;SI = acl + bdl
  29. M2:    mov    AX,CX        ;AX = a
  30.     mul    BX        ;AX = abl, DX = abh
  31.     add    DX,SI        ;AX = abl, DX = abh + acl + bdl
  32.     pop    SI
  33.     ret
  34. c_endp    _LMUL@
  35.  
  36. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  37. ; Unsigned long divide.
  38. ; Input:
  39. ;    [DX,AX],[CX,BX]
  40. ; Output:
  41. ;    [DX,AX] = [DX,AX] / [CX,BX]
  42. ;    [CX,BX] = [DX,AX] % [CX,BX]
  43. ;    SI,DI    destroyed
  44.  
  45. func    uldiv
  46.     tst    DX
  47.     jnz    D3
  48.     ;High words are 0, we can use the DIV instruction
  49.     div    BX
  50.     mov    BX,DX
  51.     mov    DX,CX            ;DX = CX = 0
  52.     ret
  53.  
  54. D3:    ;Divide [DX,AX] by BX
  55.     mov    CX,AX
  56.     mov    AX,DX
  57.     clr    DX
  58.     div    BX
  59.     xchg    CX,AX
  60.     div    BX
  61.     ;CX,AX = result
  62.     ;DX = remainder
  63.     mov    BX,DX
  64.     mov    DX,CX
  65.     clr    CX
  66.     ret
  67. c_endp    uldiv
  68.  
  69. func    _ULDIV@
  70.     jcxz    uldiv
  71.  
  72.     push    BP
  73.  
  74.     ;left justify [CX,BX] and leave count of shifts + 1 in BP
  75.  
  76.     mov    BP,1            ;at least 1 shift
  77.     tst    CH            ;left justified?
  78.     js    L1            ;yes
  79.     jnz    L2
  80.     add    BP,8
  81.     mov    CH,CL
  82.     mov    CL,BH
  83.     mov    BH,BL
  84.     clr    BL            ;[CX,BX] <<= 8
  85.     tst    CH
  86.     js    L1
  87. L2:    inc    BP            ;another shift
  88.     shl    BX,1
  89.     rcl    CX,1            ;[CX,BX] <<= 1
  90.     jno    L2            ;not left justified yet
  91.  
  92. L1:    mov    SI,CX
  93.     mov    DI,BX            ;[SI,DI] = divisor
  94.  
  95.     mov    CX,DX
  96.     mov    BX,AX            ;[CX,BX] = [DX,AX]
  97.     clr    AX
  98.     cwd                ;[DX,AX] = 0
  99. L4:    .if    SI a CX, L3        ;is [CX,BX] > [SI,DI]?
  100.     jb    L5            ;definitely less than
  101.     .if    DI a BX, L3        ;check low order word
  102. L5:    sub    BX,DI
  103.     sbb    CX,SI            ;[CX,BX] -= [SI,DI]
  104.     stc                ;rotate in a 1
  105. L3:    rcl    AX,1
  106.     rcl    DX,1            ;[DX,AX] = ([DX,AX] << 1) + C
  107.     shr    SI,1
  108.     rcr    DI,1            ;[SI,DI] >>= 1
  109.     dec    BP            ;control count
  110.     jne    L4
  111.     pop    BP
  112.     ret
  113.  
  114. div0:    mov    AX,-1
  115.     cwd                ;quotient is -1
  116. ;    clr    CX
  117. ;    mov    BX,CX            ;remainder is 0 (CX and BX already 0)
  118.     pop    BP
  119.     ret
  120.  
  121. L10:    tst    CX            ;[CX,BX] negative?
  122.     jns    _ULDIV@            ;no (all is positive)
  123.     neg32    CX,BX
  124.     callm    _ULDIV@
  125. L12:    neg32    DX,AX            ;quotient is negative
  126.     ret
  127. c_endp    _ULDIV@
  128.  
  129.  
  130. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  131. ; Signed long divide.
  132. ; Input:
  133. ;    [DX,AX],[CX,BX]
  134. ; Output:
  135. ;    [DX,AX] = [DX,AX] / [CX,BX]
  136. ;    [CX,BX] = [DX,AX] % [CX,BX]
  137. ;    SI,DI    destroyed
  138.  
  139. func    _LDIV@
  140.     tst    DX            ;[DX,AX] negative?
  141.     jns    L10            ;no
  142.     neg32    DX,AX            ;[DX,AX] = -[DX,AX]
  143.     tst    CX            ;[CX,BX] negative?
  144.     jns    L11            ;no
  145.     neg32    CX,BX
  146.     callm    _ULDIV@
  147.     neg32    CX,BX            ;remainder same sign as DiviDenD
  148.     ret
  149.  
  150. L11:    callm    _ULDIV@
  151.     neg32    CX,BX            ;remainder same sign as DiviDenD
  152.     jmps    L12
  153.  
  154. c_endp    _LDIV@
  155.  
  156.  
  157. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  158. ; Compare [DX,AX] with [CX,BX]
  159. ; Signed
  160.  
  161. func    _LCMP@
  162.     cmp    DX,CX
  163.     jne    C1
  164.     push    DX
  165.     clr    DX
  166.     cmp    AX,BX
  167.     jz    C2
  168.     ja    C3
  169.     dec    DX
  170.     pop    DX
  171.     ret
  172.  
  173. C3:    inc    DX
  174. C2:    pop    DX
  175. C1:    ret
  176. c_endp    _LCMP@
  177.  
  178.     endcode    lmath
  179.  
  180.     end
  181.