home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / tnylib.lzh / _XN.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-11-21  |  3.9 KB  |  175 lines

  1. include compiler.inc
  2.     ttl    _XN, 1.04, 08-28-86 jwk
  3.  
  4. ;binary to ascii conversion
  5. ;
  6. ;        call is _x?(n,bfr,base) unsigned long n; char *bfr;
  7. ;            int base; /* only _xn takes base */
  8. ;        BUFFER MUST BE AT LEAST 12 BYTES, NO CHECK MADE!!!
  9. ;
  10. ;
  11. ;    REGISTERS at entry--
  12. ;        AX:    unknown
  13. ;        BX:    unknown
  14. ;        CX:    unknown
  15. ;        DX:    unknown
  16. ;        SI:    unknown
  17. ;        DI:    unknown
  18. ;        BP:    Frame pointer of calling routine.
  19. ;        DS:    unknown
  20. ;        ES:    unknown
  21. ;
  22. ;          at exit--
  23. ;        AX:    Offset of "bfr" start, same as supplied.
  24. ;        BX:    zero
  25. ;        CX:    zero
  26. ;        DX:    Segment of "bfr" start (if not small model).
  27. ;        SI:    Restored.
  28. ;        DI:    Restored.
  29. ;        BP:    Restored.
  30. ;        DS:    Restored.
  31. ;        ES:    Segment of "bfr"
  32. ;
  33. ;    SIDE EFFECTS (including effect on RAM):
  34. ;        Converts its argument (as unsigned long) to ASCII,
  35. ;        using supplied base in range from 2 to 36 inclusive, and
  36. ;        stores characters in buffer as null-terminated string.
  37. ;
  38.  
  39.     dseg
  40.  
  41.     cseg
  42.  
  43.     procdef    _xn <<n1,word>,<n2,word>,<bfr,ptr>,<base,word>>
  44.     pushreg
  45.     mov    si,base
  46.     jmp    short    xc
  47. ;
  48.     entrdef    _xh
  49.     pushreg
  50.     mov    si,16
  51.     jmp    short    xc
  52. ;
  53.     entrdef    _xo
  54.     pushreg
  55.     mov    si,8
  56.     jmp    short    xc
  57. ;
  58.     entrdef    _xd
  59.     pushreg
  60.     mov    si,10
  61.  
  62. xc:
  63.     mov    ax,n1        ;LSW of number
  64.     mov    dx,n2        ;MSW of number
  65.     ldptr    di,bfr        ;buffer address to use
  66.     call    cvtl        ;macro not needed, no args to pass
  67.     clc
  68.     retptrm    bfr
  69.  
  70.     pend    _xn
  71.  
  72.     internal    cvtl
  73. ;
  74. ;    internal routine to perform the conversion and store chars
  75. ;    (chars are stored in reverse sequence, then un-reversed)
  76. ;
  77. ;    REGISTERS at entry--
  78. ;        AX:    LSW of number to convert
  79. ;        BX:    unknown
  80. ;        CX:    unknown
  81. ;        DX:    MSW of number to convert
  82. ;        SI:    base quantity (2 to 36)
  83. ;        DI:    buffer address offset to start
  84. ;        BP:    Frame pointer of calling routine (_xn).
  85. ;        DS:    unknown
  86. ;        ES:    buffer address segment
  87. ;
  88. ;          at exit--
  89. ;        AX:    last pair of chars swapped
  90. ;        BX:    zero
  91. ;        CX:    zero
  92. ;        DX:    zero
  93. ;        SI:    offset near middle of buffer
  94. ;        DI:    offset near middle of buffer
  95. ;        BP:    Restored
  96. ;        DS:    unchanged
  97. ;        ES:    buffer address segment
  98. ;
  99. ;    SIDE EFFECTS (including effect on RAM):
  100. ;        Stores remainders, converted to ASCII, at ES:DI,
  101. ;        then reverses chars in buffer to the correct sequence
  102. ;        using the K&P "swap the ends" algorithm.
  103.  
  104.     push    bp        ;don't use macro here; bp-4 offset
  105.     mov    bp,sp        ;...must not be modified!
  106.     push    di        ;save buffer start for "reverse"
  107.     xor    bx,bx        ;clear work register
  108.     push    bx        ;clear the dividend work reg
  109.     cld            ;set for ascending STOSB action
  110.     xchg    ax,bx
  111.     stosb            ;put in terminating NULL first
  112.     xchg    ax,bx
  113. ;
  114. ;    this does 32-bit division/remainder arithmetic
  115. ;
  116. cv0:
  117.     mov    cx,32        ;32 bits must be shifted
  118. cv1:
  119.     xchg    cx,[bp-4]    ;swap loop count/work reg
  120.     shl    ax,1        ;puts 0 bit in quotient
  121.     rcl    dx,1
  122.     rcl    bx,1
  123.     rcl    cx,1
  124.     or    cx,cx        ;will it go?
  125.     jnz    cv2        ;yes since base is < 8 bits
  126.     cmp    si,bx        ;maybe...
  127.     ja    cv3        ;no
  128. cv2:
  129.     sub    bx,si        ;32-bit subtract
  130.     sbb    cx,0
  131.     inc    ax        ;sets low bit of Q to 1
  132. cv3:
  133.     xchg    cx,[bp-4]    ;swap back
  134.     loop    cv1        ;do it for all 32 bits
  135. ;
  136. ;    quotient in DX:AX, remainder ( < base ) in BL, BH==0
  137. ;
  138.     xchg    ax,bx        ;set up to save remainder
  139.     add    al,'0'        ;convert to ASCII
  140.     cmp    al,'9'
  141.     jbe    cv4        ;not in A-F range
  142.     add    al,7        ;map to UC alpha
  143. cv4:
  144.     stosb            ;put it in buffer
  145.     mov    al,ah        ;clear work reg for next time
  146.     xchg    ax,bx        ;get LSW of quotient back
  147.     or    ax,ax        ;and test for conversion done
  148.     jnz    cv0        ;no, go do another divide
  149.     or    dx,dx        ;maybe...
  150.     jnz    cv0        ;no
  151. ;
  152. ;    this point is not reached until conversion is complete
  153. ;
  154. cv5:
  155.     pop    ax        ;balance the stack (work reg word)
  156.     pop    si        ;offset to front of buffer
  157. cv6:
  158.     dec    di
  159.     cmp    si,di        ;check for overlap (or same)
  160.     jae    cv7        ;yep, all swapped around
  161.     mov    ah,es:[si]    ; note that lodsb/stosb would
  162.     mov    al,es:[di]    ; take more code because one
  163.     mov    es:[di],ah    ; is incrementing while the
  164.     mov    es:[si],al    ; other is decrementing
  165.     inc    si
  166.     jmp    cv6
  167. cv7:
  168.     mov    sp,bp
  169.     pop    bp
  170.     ret
  171.  
  172. cvtl    endp            ;pend macro is only for public procs
  173. ;
  174.     finish
  175.