home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / stdlib.zip / SPRINTF.ASM < prev    next >
Assembly Source File  |  1990-07-09  |  16KB  |  819 lines

  1. stdlib        segment    para public 'slcode'
  2.         assume    cs:stdlib
  3.         extrn    sl_ISize:far, sl_ULSize:far
  4.         extrn    sl_LSize:far, sl_USize:far
  5.         extrn    sl_itoa:far, sl_free:far
  6.         extrn    sl_wtoa:far, sl_ltoa:far
  7.         extrn    sl_ultoa:far, sl_htoa:far
  8.         extrn    sl_utoa:far
  9.         extrn    sl_malloc:far, sl_realloc:far
  10. ;
  11. ;
  12. ;
  13. ; Sprintf- Like the "C" routine by the same name.  Calling sequence:
  14. ;
  15. ;               call    sprintf
  16. ;               db      "format string",0
  17. ;               dd      item1, item2, ..., itemn
  18. ;
  19. ; Just like the PRINTF routine except it performs an in-memory format
  20. ; operation rather than printing the data to the current output device.
  21. ; Returns a pointer to the formatted string in ES:DI.
  22. ; See the PRINTF routine for more details about this guy.
  23. ;
  24. ;
  25. cr        equ    0dh
  26. ff        equ    0ch
  27. lf        equ    0ah
  28. tab        equ    09h
  29. bs        equ    08h
  30. ;
  31. RtnAdrs        equ    2[bp]
  32. ;
  33. ;
  34. aindex        dw    ?
  35. aptr        dd    ?
  36. ;
  37. ;
  38. ; sp_BufSize is a public variable so the user can adjust the size.
  39. ;
  40.         public    sp_BufSize
  41. sp_BufSize    dw    2048
  42. ;
  43. ;
  44.         public    sl_sprintf
  45. sl_sprintf    proc    far
  46.         push    bp
  47.         mov    bp, sp
  48.         pushf
  49.         push    ax cx
  50. ;
  51. ; Request some memory from the system.  If there isn't enough available,
  52. ; try half as much and repeat.  If there is no memory available, return
  53. ; with the carry set.
  54. ;
  55.         mov    cx, sp_BufSize
  56. TryAgain:    call    sl_malloc
  57.         jnc    DoSPRINTF
  58.         shr    cx, 1
  59.         cmp    cx, 128            ;Need at least 128 bytes.
  60.         jae    TryAgain
  61.         pop    cx ax
  62.         popf
  63.                 pop    bp
  64.         stc
  65.         ret
  66. ;
  67. ; The following code simulates a far call to sbprintf.  We can't make the
  68. ; call because we need to skip the MOV BP, SP instruction which appears
  69. ; at the beginning of the code.
  70. ;
  71. DoSPRINTF:         push    cs            ;Push fake return address
  72.         mov    ax, offset RA
  73.         push    ax
  74.         push    bp            ;Push stuff on stack
  75.         pushf
  76.         push    ax bx cx dx di si es ds
  77.         jmp    sl_sbprintf2
  78. ;
  79. ; Return back to this point from sbprintf.
  80. ;
  81. RA:        push    di
  82.         mov    cx, 1
  83.         mov    al, ch
  84. FindLength:    cmp    al, es:[di]
  85.         jz    AtEnd
  86.         inc    cx
  87.         inc    di
  88.         jmp    FindLength
  89. ;
  90. AtEnd:        pop    di
  91.         call    sl_realloc
  92.         pop    cx ax
  93.         popf
  94.                 pop    bp
  95.         clc
  96.         ret        
  97. sl_sprintf    endp
  98. ;
  99. ;
  100. ;
  101. ;
  102. ; SBPRINTF- Like sprintf except it doesn't allocate storage for the
  103. ; formatted string.  Instead, you must pass it the address of a suitable
  104. ; buffer in es:di.
  105. ;
  106. ;
  107.         public  sl_sbprintf
  108. sl_sbprintf    proc    far
  109.         push    bp
  110.         mov    bp, sp
  111.         pushf
  112.         push    ax bx cx dx di si es ds
  113. ;
  114. ; Save ptr to buffer area.
  115. ;
  116. sl_sbprintf2:    mov    word ptr cs:aptr, di
  117.         mov    word ptr cs:aptr+2, es
  118.         mov    cs:aindex, 0
  119. ;
  120. ; Get pointers to the return address (format string).
  121. ;
  122.         cld
  123.         les    di, RtnAdrs
  124.         lds    si, RtnAdrs
  125. ;
  126. ; Okay, search for the end of the format string.  After these instructions,
  127. ; di points just beyond the zero byte at the end of the format string.  This,
  128. ; of course, points at the first address beyond the format string.
  129. ;
  130.         mov    al, 0
  131.         mov    cx, 65535
  132.     repne    scasb
  133. ;
  134. PrintItems:    lodsb            ;Get char si points at.
  135.         cmp    al, 0        ;EOS?
  136.         jz    PrintfDone
  137.         cmp    al, "%"        ;Start of a format string?
  138.         jz    FmtItem
  139.         cmp    al, "\"        ;Escape character?
  140.         jnz    PrintIt
  141.         call    GetEscChar
  142. PrintIt:    call    PutIt
  143.         jmp    PrintItems
  144. ;
  145. FmtItem:    call    GetFmtItem    ;Process the format item here.
  146.         jmp    PrintItems
  147. ;
  148. PrintfDone:    mov    RtnAdrs, di    ;Put out new return address.
  149.         pop    ds
  150.         pop    es
  151.         pop    si
  152.         pop    di
  153.         pop    dx
  154.         pop    cx
  155.         pop    bx
  156.         pop    ax
  157.         pop    bp
  158.         popf
  159.         clc
  160.         ret
  161. sl_sbprintf    endp
  162. ;
  163. ; GetEscChar- Handles items immediately following the escape character "\".
  164. ;
  165. ;    Special escape characters (upper/lower case is acceptable):
  166. ;
  167. ;        n    Newline (cr/lf)
  168. ;        t    tab
  169. ;        b    backspace
  170. ;        r    return
  171. ;        l    line feed
  172. ;        f    formfeed
  173. ;        \    \
  174. ;        %    &
  175. ;        0xhh    Char with hex character code hh.  Must have exactly
  176. ;            two hexadecimal digits.
  177. ;
  178. GetEscChar    proc    near
  179.         lodsb            ;Get next character
  180.         cmp    al, 'n'
  181.         je    RtnNL
  182.         cmp    al, 'N'
  183.         je    RtnNL
  184.         cmp    al, 't'
  185.         je    RtnTab
  186.         cmp    al, 'T'
  187.         je    RtnTab
  188.         cmp    al, 'b'
  189.         je    RtnBS
  190.         cmp    al, 'B'
  191.         je    RtnBS
  192.         cmp    al, 'r'
  193.         je    RtnRtn
  194.         cmp    al, 'R'
  195.         je    RtnRtn
  196.         cmp    al, 'l'
  197.         je    RtnLF
  198.         cmp    al, 'L'
  199.         je    RtnLF
  200.         cmp    al, 'f'
  201.         je    RtnFF
  202.         cmp    al, 'F'
  203.         je    RtnFF
  204. ;
  205. ; Check for the presence of a 0xhh value here:
  206. ;
  207.         cmp    al, '0'
  208.         jne    RtnChar
  209.         cmp    byte ptr [si], 'x'
  210.         je    GetHex
  211.         cmp    byte ptr [si], 'X'
  212.         jne    RtnChar
  213. ;
  214. ; Okay, process the hex value here.  Note that exactly two hex digits must
  215. ; follow the 0x.
  216. ;
  217. GetHex:        inc    si        ;Point at first hex digit.
  218.         lodsb            ;Get first hex digit.
  219.         and    al, 05fh    ;l.c. -> u.c.
  220.         cmp    al, 'A'
  221.         jb    GotIt
  222.         sub    al, '7'
  223. GotIt:        shl    al, 1        ;Put into H.O. nibble.
  224.         shl    al, 1
  225.         shl    al, 1
  226.         shl    al, 1
  227.         mov    ah, al        ;Save for later
  228.         lodsb            ;Get next char.
  229.         and    al, 05fh
  230.         cmp    al, 'A'
  231.         jb    GotIt2
  232.         sub    al, '7'
  233. GotIt2:        and    al, 0fh
  234.         or    al, ah
  235.         ret            ;Return hex constant.
  236. ;
  237. ; RtnNL (return Newline) cheats.  It needs to return two characters.
  238. ; Since GetEscChar only returns a single character, this code goes ahead
  239. ; and calls putc to output the CR and the returns the LF.
  240. ;
  241. RtnNL:        mov    al, cr
  242.         call    PutIt
  243.         mov    al, lf
  244.         ret
  245. ;
  246. RtnTab:        mov    al, tab
  247.         ret
  248. ;
  249. RtnBS:        mov    al, bs
  250.         ret
  251. ;
  252. RtnRtn:        mov    al, cr
  253.         ret
  254. ;
  255. RtnLF:        mov    al, lf
  256.         ret
  257. ;
  258. RtnFF:        mov    al, ff
  259. RtnChar:    ret
  260. ;
  261. GetEscChar    endp
  262. ;
  263. ;
  264. ;
  265. GetFmtItem    proc    near
  266.         lodsb                ;Get char beyond "%"
  267. ;
  268.         mov    cx, 1            ;Default field width is 1.
  269.         mov    dl, 0            ;Default is right justified
  270.         mov    dh, ' '            ;Default fill char is space.
  271.         mov    ah, ' '            ;Assume straight ptr, not handle.
  272. ;
  273. ; See if the user wants the value left justified:
  274. ;
  275.         cmp    al, '-'
  276.         jne    NotLeftJust
  277.         inc    dl            ;Set to right justified
  278.         lodsb                ;Get next character.
  279. ;
  280. ; See if the user wants to change the padding character.
  281. ;
  282. NotLeftJust:    cmp    al, '\'
  283.         jne    NoPadChange
  284.         lodsb                ;Get Padding Character.
  285.         mov    dh, al            ;Save padding character.
  286.         lodsb                ;Get next character
  287. ;
  288. ; See if the user wants a different field width:
  289. ;
  290. NoPadChange:    cmp    al, '0'
  291.         jb    NoFldWidth
  292.         cmp    al, '9'
  293.         ja    NoFldWidth
  294.         call    GetDecVal
  295. ;
  296. ; See if the user wants to specify a handle rather than a straight pointer
  297. ;
  298. NoFldWidth:    cmp    al, '^'
  299.         jne     ChkFmtChars
  300.         mov    ah, al
  301.         lodsb                ;Skip "^" character
  302. ;
  303. ; Okay, process the format characters down here.
  304. ;
  305. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  306.         cmp    al, 'D'
  307.         je    PrintDec
  308.         cmp    al, 'I'
  309.         je    PrintDec
  310.         cmp    al, 'C'
  311.         je    PrintChar
  312. ;
  313.         cmp    al, 'X'
  314.         jne    TryH
  315.         jmp    PrintHexWord
  316. ;
  317. TryH:        cmp    al, 'H'
  318.         jne    TryU
  319.         jmp    PrintHexByte
  320. ;
  321. TryU:        cmp    al, 'U'
  322.         jne    TryString
  323.         jmp    PrintUDec
  324. ;
  325. TryString:    cmp    al, 'S'
  326.         jne    TryLong
  327.         jmp    PrintString
  328. ;
  329. TryLong:    cmp    al, 'L'
  330.         jne    Default
  331. ;
  332. ; If we've got the "L" modifier, this is a long value to print, get the
  333. ; data type character as the next value:
  334. ;
  335.         lodsb
  336.         and    al, 05fh        ;l.c. -> U.C.
  337.         cmp    al, 'D'
  338.         je    JmpDec
  339.         cmp    al, 'I'
  340.         jne    TryLU
  341. JmpDec:        jmp    LongDec
  342. ;
  343. TryLU:        cmp    al, 'U'
  344.         jne    TryX
  345.         jmp    LongU
  346. ;
  347. TryX:        cmp    al, 'X'
  348.         jne    Default
  349.         jmp    LongX
  350. ;
  351. ;
  352. ;
  353. ; If none of the above, simply return without printing anything.
  354. ;
  355. Default:        ret
  356. ;
  357. ;
  358. ;
  359. ;
  360. ;
  361. ; Print a signed decimal value here.
  362. ;
  363. PrintDec:    call    GetPtr            ;Get next pointer into ES:BX
  364.         mov    ax, es:[bx]        ;Get value to print.
  365.         call    sl_ISize        ;Get the size of this guy.
  366.         sub    cx, ax                 ;Compute padding
  367.         mov    ax, es:[bx]        ;Retrieve value to print.
  368.         js    NoPadDec        ;Is CX negative?
  369.         cmp    dl, 0            ;Right justified?
  370.         jne    LeftJustDec
  371.         call    PrintPad        ;Print padding characters
  372.         call    PutIti            ;Print the integer
  373.         ret                ;We're done!
  374. ;
  375. ; Print left justified value here.
  376. ;
  377. LeftJustDec:    call    PutIti
  378.         call    PrintPad
  379.         ret
  380. ;
  381. ; Print non-justified value here:
  382. ;
  383. NoPadDec:    call    PutIti
  384.         ret
  385. ;
  386. ;
  387. ;
  388. ; Print a character variable here.
  389. ;
  390. PrintChar:    call    GetPtr            ;Get next pointer into ES:BX
  391.         mov    al, es:[bx]        ;Retrieve value to print.
  392.                 dec    cx
  393.         js    NoPadChar        ;Is CX negative?
  394.         cmp    dl, 0            ;Right justified?
  395.         jne    LeftJustChar
  396.         call    PrintPad        ;Print padding characters
  397.         call    PutIt            ;Print the character
  398.         ret                ;We're done!
  399. ;
  400. ; Print left justified value here.
  401. ;
  402. LeftJustChar:    call    PutIt
  403.         call    PrintPad
  404.         ret
  405. ;
  406. ; Print non-justified character here:
  407. ;
  408. NoPadChar:    call    PutIt
  409.         ret
  410. ;
  411. ;
  412. ;
  413. ;
  414. ; Print a hexadecimal word value here.
  415. ;
  416. PrintHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  417.         mov    ax, es:[bx]        ;Get value to print.
  418.         sub    cx, 4            ;Compute padding
  419.         js    NoPadHexW        ;Is CX negative?
  420.         cmp    dl, 0            ;Right justified?
  421.         jne    LeftJustHexW
  422.         call    PrintPad        ;Print padding characters
  423.         call    PutItw            ;Print the hex value
  424.         ret                ;We're done!
  425. ;
  426. ; Print left justified value here.
  427. ;
  428. LeftJustHexW:    call    PutItw
  429.         call    PrintPad
  430.         ret
  431. ;
  432. ; Print non-justified value here:
  433. ;
  434. NoPadHexW:    call    PutItw
  435.         ret
  436. ;
  437. ;
  438. ;
  439. ;
  440. ; Print hex bytes here.
  441. ;
  442. ;
  443. PrintHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  444.         mov    ax, es:[bx]        ;Get value to print.
  445.         sub    cx, 4            ;Compute padding
  446.         js    NoPadHexB        ;Is CX negative?
  447.         cmp    dl, 0            ;Right justified?
  448.         jne    LeftJustHexB
  449.         call    PrintPad        ;Print padding characters
  450.         call    PutIth            ;Print the hex value
  451.         ret                ;We're done!
  452. ;
  453. ; Print left justified value here.
  454. ;
  455. LeftJustHexB:    call    PutIth
  456.         call    PrintPad
  457.         ret
  458. ;
  459. ; Print non-justified value here:
  460. ;
  461. NoPadHexB:    call    PutIth
  462.         ret
  463. ;
  464. ;
  465. ;
  466. ; Output unsigned decimal numbers here:
  467. ;
  468. PrintUDec:    call    GetPtr            ;Get next pointer into ES:BX
  469.         mov    ax, es:[bx]        ;Get value to print.
  470.         call    sl_USize        ;Get the size of this guy.
  471.         sub    cx, ax                 ;Compute padding
  472.         mov    ax, es:[bx]        ;Retrieve value to print.
  473.         js    NoPadUDec        ;Is CX negative?
  474.         cmp    dl, 0            ;Right justified?
  475.         jne    LeftJustUDec
  476.         call    PrintPad        ;Print padding characters
  477.         call    PutItu            ;Print the integer
  478.         ret                ;We're done!
  479. ;
  480. ; Print left justified value here.
  481. ;
  482. LeftJustUDec:    call    PutItu
  483.         call    PrintPad
  484.         ret
  485. ;
  486. ; Print non-justified value here:
  487. ;
  488. NoPadUDec:    call    PutItu
  489.         ret
  490. ;
  491. ;
  492. ;
  493. ;
  494. ; Output a string here:
  495. ;
  496. PrintString:    call    GetPtr            ;Get next pointer into ES:BX
  497. ;
  498. ; Compute the length of the string:
  499. ;
  500.         push    di
  501.         push    cx
  502.         mov    cx, -1
  503.         mov    di, bx
  504.         mov    al, 0
  505.     repne    scasb
  506.         mov    ax, cx
  507.         neg    ax
  508.         dec    ax
  509.         dec    ax
  510.         pop    cx
  511.         pop    di
  512.         sub    cx, ax            ;Field width - String Length.
  513. ;
  514.         js    NoPadStr        ;Is CX negative?
  515.         cmp    dl, 0            ;Right justified?
  516.         jne    LeftJustStr
  517.         call    PrintPad        ;Print padding characters
  518.         call    Puts            ;Print the string
  519.         ret                ;We're done!
  520. ;
  521. ; Print left justified value here.
  522. ;
  523. LeftJustStr:    call    Puts
  524.         call    PrintPad
  525.         ret
  526. ;
  527. ; Print non-justified value here:
  528. ;
  529. NoPadStr:    call    Puts
  530.         ret
  531. GetFmtItem    endp
  532. ;
  533. ;
  534. ;
  535. ; Print a signed long decimal value here.
  536. ;
  537. LongDec:    call    GetPtr            ;Get next pointer into ES:BX
  538.         mov    ax, es:[bx]        ;Get value to print.
  539.         push    dx
  540.         mov    dx, es:2[bx]
  541.         call    sl_LSize        ;Get the size of this guy.
  542.         pop    dx
  543.         sub    cx, ax                 ;Compute padding
  544.         mov    ax, es:[bx]        ;Retrieve value to print.
  545.         js    NoPadLong        ;Is CX negative?
  546.         cmp    dl, 0            ;Right justified?
  547.         jne    LeftJustLong
  548.         call    PrintPad        ;Print padding characters
  549.         mov    dx, es:2[bx]        ;Get H.O. word
  550.         call    PutItL            ;Print the integer
  551.         ret                ;We're done!
  552. ;
  553. ; Print left justified value here.
  554. ;
  555. LeftJustLong:    push    dx
  556.         mov    dx, es:2[bx]        ;Get H.O. word
  557.         call    PutItL
  558.         pop    dx
  559.         call    PrintPad
  560.         ret
  561. ;
  562. ; Print non-justified value here:
  563. ;
  564. NoPadLong:    mov    dx, es:2[bx]        ;Get H.O. word
  565.         call    PutItl
  566.         ret
  567. ;
  568. ;
  569. ; Print an unsigned long decimal value here.
  570. ;
  571. LongU:        call    GetPtr            ;Get next pointer into ES:BX
  572.         mov    ax, es:[bx]        ;Get value to print.
  573.         push    dx
  574.         mov    dx, es:[bx]
  575.         call    sl_ULSize        ;Get the size of this guy.
  576.         pop    dx
  577.         sub    cx, ax                 ;Compute padding
  578.         mov    ax, es:[bx]        ;Retrieve value to print.
  579.         js    NoPadULong        ;Is CX negative?
  580.         cmp    dl, 0            ;Right justified?
  581.         jne    LeftJustULong
  582.         call    PrintPad        ;Print padding characters
  583.         mov    dx, es:2[bx]        ;Get H.O. word
  584.         call    PutItUL            ;Print the integer
  585.         ret                ;We're done!
  586. ;
  587. ; Print left justified value here.
  588. ;
  589. LeftJustULong:    mov    dx, es:2[bx]        ;Get H.O. word
  590.         call    PutItUL
  591.         call    PrintPad
  592.         ret
  593. ;
  594. ; Print non-justified value here:
  595. ;
  596. NoPadULong:    mov    dx, es:2[bx]        ;Get H.O. word
  597.         call    Putitul
  598.         ret
  599. ;
  600. ;
  601. ; Print a long hexadecimal value here.
  602. ;
  603. LongX:        call    GetPtr            ;Get next pointer into ES:BX
  604.         sub    cx, 8            ;Compute padding
  605.         js    NoPadXLong        ;Is CX negative?
  606.         cmp    dl, 0            ;Right justified?
  607.         jne    LeftJustXLong
  608.         call    PrintPad        ;Print padding characters
  609.         mov    ax, es:2[bx]        ;Get H.O. word
  610.         call    PutItw
  611.         mov    ax, es:[bx]
  612.         call    PutItw
  613.         ret                ;We're done!
  614. ;
  615. ; Print left justified value here.
  616. ;
  617. LeftJustxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  618.         call    PutItw
  619.         mov    ax, es:[bx]        ;Get L.O. word
  620.         call    PutItw
  621.         call    PrintPad
  622.         ret
  623. ;
  624. ; Print non-justified value here:
  625. ;
  626. NoPadxLong:    mov    ax, es:2[bx]        ;Get H.O. word
  627.         call    PutItw
  628.         mov    ax, es:[bx]
  629.         call    PutItw
  630.         ret
  631. ;
  632. ;
  633. ;
  634. ;
  635. ; Puts- Outputs the zero terminated string pointed at by ES:BX.
  636. ;
  637. Puts        proc    near
  638. PutsLp:        mov    al, es:[bx]
  639.         cmp    al, 0
  640.         je    PutsDone
  641.         call    putIt
  642.         inc    bx
  643.         jmp    PutsLp
  644. ;
  645. PutsDone:    ret
  646. Puts        endp
  647. ;
  648. ;
  649. ;
  650. ;
  651. ;
  652. ; PrintPad-    Prints padding characters.  Character to print is in DH.
  653. ;        We must print it CX times.  CX must be greater than zero.
  654. ;
  655. PrintPad    proc    near
  656.         push    ax
  657.         mov    al, dh
  658.         jcxz    NoPadding
  659. PPLoop:        call    PutIt
  660.         loop    PPLoop
  661. NoPadding:    pop    ax
  662.         ret
  663. PrintPad    endp
  664. ;
  665. ;
  666. ;
  667. ;
  668. ;
  669. ; GetPtr- Grabs the next pointer which DS:DI points at and returns this
  670. ;      far pointer in ES:BX.
  671. ;
  672. GetPtr        proc    near
  673.         les    bx, [di]
  674.         add    di, 4
  675. ;
  676. ; See if this is a handle rather than a pointer.
  677. ;
  678.         cmp    ah, '^'
  679.         jne    NotHandle
  680.         les    bx, es:[bx]
  681. NotHandle:    ret
  682. GetPtr        endp
  683. ;
  684. ;
  685. ;
  686. ;
  687. ;
  688. ; GetDecVal-    Converts the string of decimal digits in AL and [SI] into
  689. ;        an integer and returns this integer in CX.
  690. ;
  691. GetDecVal    proc    near
  692.         push    dx
  693.         dec    si
  694.         xor    cx, cx
  695. DecLoop:    lodsb
  696.         cmp    al, '0'
  697.         jb    NoMore
  698.         cmp    al, '9'
  699.         ja    NoMore
  700.         and    al, 0fh
  701.         shl    cx, 1            ;Compute CX := CX*10 + al
  702.         mov    dx, cx
  703.         shl    cx, 1
  704.         shl    cx, 1
  705.         add    cx, dx
  706.         add    cl, al
  707.         adc    ch, 0
  708.         jmp    DecLoop
  709. NoMore:        pop    dx
  710.         ret
  711. GetDecVal    endp
  712. ;
  713. ;
  714. ; PutItL - outputs the unsigned long value in AX to the string.
  715. ;
  716. PutItL        proc
  717.         push    bx cx es si ds di
  718.         call    sl_ltoa
  719.         call    ConCat
  720.         pop    di ds si es cx bx
  721.         ret
  722. PutItL        endp
  723. ;
  724. ;
  725. ; PutItUL - outputs the unsigned long value in AX to the string.
  726. ;
  727. PutItUL        proc
  728.         push    bx cx es si ds di
  729.         call    sl_ultoa
  730.         call    ConCat
  731.         pop    di ds si es cx bx
  732.         ret
  733. PutItUL        endp
  734. ;
  735. ;
  736. ;
  737. ; PutItw - outputs the hexadecimal value in AX to the string.
  738. ;
  739. PutItw        proc
  740.         push    bx cx es si ds di
  741.         call    sl_wtoa
  742.         call    ConCat
  743.         pop    di ds si es cx bx
  744.         ret
  745. PutItw        endp
  746. ;
  747. ; PutIth - outputs the hexadecimal value in AL to the string.
  748. ;
  749. PutIth        proc
  750.         push    bx cx es si ds di
  751.         call    sl_htoa
  752.         call    ConCat
  753.         pop    di ds si es cx bx
  754.         ret
  755. PutIth        endp
  756. ;
  757. ;
  758. ;
  759. ; PutIti - outputs the integer in AX to the string.
  760. ;
  761. PutIti        proc
  762.         push    bx cx es si ds di
  763.         call    sl_itoa
  764.         call    ConCat
  765.         pop    di ds si es cx bx
  766.         ret
  767. PutIti        endp
  768. ;
  769. ;
  770. ; PutItu - outputs the unsigned integer in AX to the string.
  771. ;
  772. PutItu        proc
  773.         push    bx cx es si ds di
  774.         call    sl_utoa
  775.         call    ConCat
  776.         pop    di ds si es cx bx
  777.         ret
  778. PutItu        endp
  779. ;
  780. ;
  781. ;
  782. ; ConCat- Concatenates the string pointed at by ES:DI to the end of our
  783. ;      formatted string.
  784. ;
  785. ConCat        proc    near
  786.         push    di
  787.         lds    si, cs:aptr
  788.         mov    bx, cs:aindex
  789.         sub    di, bx
  790. PILp:        mov    al, es:[di][bx]
  791.         mov    [si][bx], al
  792.         inc    bx
  793.         cmp    al, 0
  794.         jne    PILp
  795.         dec    bx
  796.         mov    cs:aindex, bx
  797.         pop    di
  798.         call    sl_free
  799.         ret
  800. ConCat        endp
  801. ;
  802. ; PutIt writes the character in AL to the string buffer area.
  803. ;
  804. PutIt        proc
  805.         push    es si bx
  806.         mov    bx, cs:aindex
  807.         les    si, cs:aptr
  808.         mov    es:[si][bx], al
  809.         mov    byte ptr es:1[si][bx], 0
  810.         inc     cs:aindex
  811.         pop    bx si es
  812.         ret
  813. PutIt        endp
  814. ;
  815. stdlib        ends
  816.         end
  817.