home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / batutl / echsys10.arc / ENVSYS.ASM < prev    next >
Assembly Source File  |  1989-09-25  |  25KB  |  600 lines

  1. ; EnvSys  : put current system data (drive, dir, time, date etc)
  2. ;           into an environment variable named first on the command line
  3. ;
  4. ; Version 1.0
  5. ;
  6. ; Free Software by TapirSoft Gisbert W.Selke, Sept 1989
  7. ;
  8. ; The environment setting stuff is
  9. ;   Copyright 1987, A. B. Krueger GPW MI 48236
  10. ;   All rights reserved. Contact "ARNY KRUEGER"
  11. ;   at the EXEC-PC BBS (414-964-5160) for permission
  12. ;   to use commercially.
  13. ;
  14. ; Otherwise, this programme may be used and copied any way you wish, but don't
  15. ; sell it. Give credit where credit is due, please. - The copyright remains
  16. ; with me and Arny; I do not guarantee proper operation of this utility; the
  17. ; whole risk of use lies with the user.
  18. ;
  19. ; Usage:   envsys <varname> <string>
  20. ;          String is put into an environment variable named varname;
  21. ;          two-char sequences introduced by '^' are replaced as indicated
  22. ;          at 'Usage' below.
  23. ;
  24. ; TASM     envsys                   or        MASM   envsys
  25. ; TLINK /t envsys                             LINK   envsys
  26. ;                                             EXEBIN envsys.exe envsys.com
  27.  
  28. BackSpace       Equ     08h
  29. LineFeed        Equ     0Ah
  30. Return          Equ     0Dh
  31. CtrlZ           Equ     1Ah
  32.  
  33.  
  34.  
  35. StuffChar       Macro   Chr                     ; macro to put a character
  36.                 Push    ax
  37.                 Mov     al, Chr                 ; into the env string
  38.                 Call    StuffIt
  39.                 Pop     ax
  40.                 Endm
  41.  
  42. Jmps            Macro   Label                   ; Jump short
  43.                 Jmp short Label
  44.                 Endm
  45.  
  46.  
  47. cseg            Segment para public
  48.  
  49.                 Extrn   env_set:near,DirString:byte,TimeBuf:byte,DateBuf:byte
  50.                 Extrn   OutLine:byte,OurStack:byte,ProgEnd:byte
  51.  
  52.  
  53.                 Org 0080h
  54. Parameter       Db      ?
  55.  
  56.                 Org 100h
  57.                 Assume cs:cseg, ds:cseg, es:cseg, ss:cseg
  58.  
  59. Start:          Jmp     Begin
  60.  
  61.                 db      'SPECIAL='
  62. Special         db      '^'
  63.  
  64.                 db      Return
  65. Copyright       db      'EnvSys 1.0 - Free software by TapirSoft'
  66.                 db      ' Gisbert W.Selke, Sept 89', Return, LineFeed
  67.                 db      'Parts copyright 1987, A. B. Krueger GPW MI 48236. '
  68.                 db      Return, LineFeed
  69.                 db      'Use at your own risk.$', BackSpace, ' '
  70.                 db      Return, LineFeed, CtrlZ
  71.  
  72. Usage1          db      Return, LineFeed, LineFeed
  73.                 db      'Usage: envsys <varname> <string>', Return, LineFeed
  74.                 db      'The string is put into the named environment '
  75.                 db      'variable', Return, LineFeed
  76.                 db      'with "$'
  77. Usage2          db      '@" replaced as indicated by @:', Return, LineFeed
  78.                 db      ': drive; \ directory; F free disk space; '
  79.                 db      'T total disk space; R free RAM;', Return, LineFeed
  80.                 db      'r RAM size; l #drives; f #floppies; P #printers; '
  81.                 db      'S #serial ports;', Return, Linefeed
  82.                 db      '7 coprocessor? L LPT1 status; V video mode; '
  83.                 db      'w screen width; t type of PC;', Return, LineFeed
  84.                 db      'v DOS version; b BIOS version; i "<" symbol; '
  85.                 db      'o ">" symbol; p "|" symbol; ', Return, LineFeed
  86.                 db      'O switch char; A author''s note; '
  87.                 db      'x char given by next 2 hex digits;', Return, LineFeed
  88.                 db      'K key typed by user; C country code; $'
  89. Usage3          db      ' currency string;', Return, LineFeed
  90.                 db      'k 1000s separator; 1 decimal separator; '
  91.                 db      '/ date separator; - time separator;'
  92.                 db      Return, LineFeed
  93.                 db      'D day; M month; Y year; W weekday; h hour; m minute; '
  94.                 db      's second; c centisecond.'
  95.                 db      Return, LineFeed, Return, LineFeed, '$'
  96.  
  97. RetVal          db      0
  98.  
  99. ModelString     db      '??80AP30??ATJRXTPC'
  100. ModelStrLen     Label   Byte
  101.  
  102. CmdLetters      db      'csmhWYMD-/1k$CpoiKxAObvtwVL7SPflRrTF\:';command letters
  103. EndCmdLetters   Label   Word
  104.  
  105. ; **NOTE**: order of CmdLetters and Dispatch is reversed w.r.t. each other!
  106.  
  107. Dispatch        dw      Drive, Directory, FreeSpace, TotalSpace, MemSize
  108.                 dw      FreeMem, LogicDrives, Floppies, Printers
  109.                 dw      CommPorts, Coproc, LptStat, VideoMode, VideoWidth
  110.                 dw      SysModel, DosVersion, BiosVersion, SwitchChar, Author
  111.                 dw      Hexnumber, KeyBoard
  112.                 dw      StdInSymbol, StdOutSymbol, PipeSymbol, CountryInfo
  113.                 dw      Currency, Thousands, Decimal, DateSep, TimeSep
  114.                 dw      Day, Month, Year, WeekDay
  115.                 dw      Hour, Minute, Second, CentiSecond
  116.  
  117.  
  118. Begin:          Mov     sp, Offset OurStack     ; point to our own stack
  119.  
  120.                 Mov     ah, 2Ch                 ; get current time right now
  121.                 Int     21h
  122.                 Mov     [TimeBuf],   ch         ; stow away
  123.                 Mov     [TimeBuf+1], cl
  124.                 Mov     [TimeBuf+2], dh
  125.                 Mov     [TimeBuf+3], dl
  126.                 Mov     ah, 2Ah                 ; get current date
  127.                 Int     21h
  128.                 Sub     cx, 1900                ; remove centuries
  129.                 Mov     word ptr [DateBuf], cx  ; stow away
  130.                 Mov     [DateBuf+2], dh
  131.                 Mov     [DateBuf+3], dl
  132.                 Mov     [DateBuf+4], al
  133.  
  134.                 Mov     si, 1+offset Parameter  ; command line string
  135.                 Xor     al, al
  136.                 Mov     [OutLine], al           ; init environment line
  137.  
  138. FindName:       Lodsb                           ; find first parameter,
  139.                 Cmp     al, Return              ; i.e., name of env variable
  140.                 Je      ShowUsage
  141.                 Cmp     al, ' '
  142.                 Je      FindName
  143.                 Cmp     al, 09h
  144.                 Je      FindName
  145.  
  146. FindName2:      Cmp     al, Return              ; stuff all its characters
  147.                 Je      EndName
  148.                 Cmp     al, ' '
  149.                 Je      EndName
  150.                 Cmp     al, 09h
  151.                 Je      EndName
  152.                 Call    StuffIt
  153.                 Lodsb
  154.                 Jmps    FindName2
  155.  
  156. EndName:        StuffChar '='                   ; prepare to set it
  157.                 Cmp     al, Return
  158.                 Je      Done
  159.                                                 ; now parse command line proper
  160.                 Cmp     al, ' '                 ; skip first char, if
  161.                 Je      NextChar                ; blank or tab
  162.                 Cmp     al, 09h
  163.                 Je      NextChar
  164.                 Cmp     al, Return
  165.                 Jne     CheckSpecials
  166. ShowUsage:      Mov     dx, offset Copyright    ; show author's note
  167.                 Mov     ah, 09h
  168.                 Int     21h
  169.                 Mov     dx, offset Usage1       ; show usage hints
  170.                 Mov     ah, 09h
  171.                 Int     21h
  172.                 Mov     dl, [Special]
  173.                 Mov     ah, 02h
  174.                 Int     21h
  175.                 Mov     dx, offset Usage2       ; more usage hints
  176.                 Mov     ah, 09h
  177.                 Int     21h
  178.                 Mov     dl, '$'
  179.                 Mov     ah, 02h
  180.                 Int     21h
  181.                 Mov     dx, offset Usage3       ; more usage hints
  182.                 Mov     ah, 09h
  183.                 Int     21h
  184.                 Mov     ax, 4CFFh               ; termination code
  185.                 Int     21h
  186.  
  187. NextChar:       Lodsb
  188.                 Cmp     al, Return              ; are we done?
  189.                 Jne     CheckSpecials
  190.  
  191. Done:           Mov     si, offset OutLine      ; point to env line
  192.                 Call    env_set                 ; set environment variable
  193.                 Or      [OutLine], 80h          ; set high bit
  194.                 Mov     si, offset OutLine      ; point to env line
  195.                 Call    env_set                 ; set environment variable
  196.                 Mov     ah, 4Ch                 ; terminate normally
  197.                 Mov     al, [RetVal]            ; return code
  198.                 Int     21h
  199.  
  200.  
  201. CheckSpecials:  Cmp     al, Special             ; is it special sequence?
  202.                 Je      DoSpecials
  203. CheckSp2:       Call    StuffIt                 ; otherwise just stuff it
  204.                 Jmps    NextChar                ; and loop
  205.  
  206. DoSpecials:     Lodsb                           ; get next char of sequence
  207.                 Mov     di, offset CmdLetters   ; look up in table
  208.                 Mov     cx, (offset EndCmdLetters) - (offset CmdLetters)
  209.                 Repne   Scasb
  210.                 Jz      DoSp2                   ; jump if found
  211.                 Cmp     al, Return              ; otherwise: are we done?
  212.                 Je      Done
  213.                 Jmps    CheckSp2                ; otherwise treat normal
  214.  
  215. DoSp2:          Add     cx, cx                  ; double for Word
  216.                 Mov     bx, cx
  217.                 Call    [dispatch+bx]           ; call the subroutine
  218.                 Jmps    NextChar
  219.  
  220.  
  221. Drive:          Mov     ah, 19h                 ; get current drive
  222.                 Int     21h
  223.                 Add     al, 41h                 ; convert to ASCII
  224.                 Mov     [RetVal], al            ; store for return
  225.                 Call    StuffIt                 ; and stuff it
  226.                 StuffChar ':'                   ; and a colon
  227.                 Ret
  228.  
  229.  
  230. Directory:      Mov     cx, si                  ; save si
  231.                 Mov     si, offset DirString    ; buffer for dir string
  232.                 Xor     dl, dl                  ; use current drive
  233.                 Mov     ah, 47h                 ; get directory string
  234.                 Int     21h
  235.  
  236.                 StuffChar '\'                   ; initial backslash
  237.  
  238. ShowDirLoop:    Lodsb                           ; get next byte
  239.                 Or      al, al                  ; is it terminating null?
  240.                 Jz      ShowDirEnd
  241.                 Call    StuffIt                 ; otherwise show char
  242.                 Jmps    ShowDirLoop             ; and loop
  243. ShowDirEnd:     Mov     si, cx                  ; restore si
  244.                 Ret
  245.  
  246.  
  247. FreeSpace:      Mov     ah, 36h                 ; get disk space
  248.                 Xor     dl, dl                  ; on default disk
  249.                 Int     21h
  250.                 Jmps    ShowSpace
  251.  
  252.  
  253. TotalSpace:     Mov     ah, 36h                 ; get disk space
  254.                 Xor     dl, dl                  ; on default disk
  255.                 Int     21h
  256.                 Mov     bx, dx                  ; choose total clusters
  257. ShowSpace:      Mul     cx                      ; dx:ax = bytes per cluster
  258.                 Mov     cx, 10                  ; prepare conversion to kB
  259. ShowSp2:        Or      dx, dx                  ; if dx > 0, shift it
  260.                 Jz      ShowSp3
  261.                 Inc     cl
  262.                 Shr     dx, 1
  263.                 Rcr     ax, 1
  264.                 Jmps    ShowSp2
  265. ShowSp3:        Mul     bx                      ; multiply by clusters
  266. ShowSp4:        Shr     dx, 1                   ; divide by 1024
  267.                 Rcr     ax, 1
  268.                 Loop    ShowSp4
  269.                 Mov     cx, 1000                ; process high digits first
  270.                 Div     cx
  271.                 Mov     [RetVal], al            ; save for return
  272.                 Mov     bx, dx                  ; save remainder
  273.                 Xor     dh, dh                  ; no minimum # of digits
  274.                 Or      ax, ax                  ; are there high digits?
  275.                 Jz      ShowSp5                 ; if not, skip
  276.                 Call    DisplayNumber           ; otherwise display
  277.                 Mov     dh, 3                   ; then minimum 3 digits
  278. ShowSp5:        Mov     ax, bx                  ; retrieve low digits
  279.                 Jmp     DisplayNumber
  280.                 Ret
  281.  
  282.  
  283. MemSize:        Int     12h                     ; get memory size
  284.                 Mov     [RetVal], ah            ; save for return
  285.                 Xor     dh, dh                  ; no minimum # of digits
  286.                 Jmp     Displaynumber
  287.  
  288.  
  289. FreeMem:        Int     12h                     ; get total RAM size
  290.                 Mov     bx, es                  ; get start address of PSP
  291.                 Mov     cl, 6                   ; convert paras to KB
  292.                 Shr     bx, cl
  293.                 Sub     ax, bx                  ; subtract from total RAM
  294.                 Mov     [RetVal], ah            ; save for return
  295.                 Xor     dh, dh
  296.                 Jmp     DisplayNumber           ; presto: free RAM!
  297.  
  298.  
  299. LogicDrives:    Mov     ah, 19h                 ; get number of logical drives
  300.                 Int     21h                     ; first, get current disk
  301.                 Mov     dl, al
  302.                 Mov     ah, 0Eh                 ; now get that number
  303.                 Int     21h
  304.                 Jmp     DisplayVeryShort
  305.  
  306.  
  307. Floppies:       Int     11h                     ; number of floppies
  308.                 Test    al, 00000001b           ; is floppy installed?
  309.                 Jne     FloppiesFound           ; skip if so
  310.                 Xor     al, al                  ; otherwise set to 0
  311.                 Jmp     DisplayVeryShort
  312.  
  313. FloppiesFound:  Mov     cl, 6                   ; isolate number of floppies
  314.                 ShR     al, cl
  315.                 And     al, 0F3h
  316.                 Inc     al
  317.                 Jmp     DisplayVeryShort
  318.  
  319.  
  320. Printers:       Int     11h                     ; number of printers
  321.                 Mov     cl, 14                  ; isolate number of printers
  322.                 ShR     ax, cl
  323.                 Jmp     DisplayVeryShort
  324.  
  325.  
  326. CommPorts:      Int     11h                     ; number of comm ports
  327.                 Mov     cl, 9                   ; isolate number of ports
  328.                 ShR     ax, cl
  329.                 And     al, 7
  330.                 Jmp     DisplayVeryShort
  331.  
  332.  
  333. Coproc:         Int     11h                     ; is coprocessor installed?
  334.                 ShR     al, 1                   ; output as 0 or 1
  335.                 And     al, 1
  336.                 Jmp     DisplayVeryShort
  337.  
  338.  
  339. LptStat:        Mov     ah, 02h                 ; get printer status
  340.                 Xor     dx, dx                  ; printer port #0
  341.                 Int     17h
  342.                 Mov     al, ah
  343.                 Xor     dl, dl
  344.                 Jmp     DisplayShort
  345.  
  346.  
  347. VideoMode:      Mov     ah, 0Fh                 ; get video mode
  348.                 Int     10h
  349.                 Xor     dh, dh
  350.                 Jmp     DisplayShort            ; display number
  351.  
  352.  
  353. VideoWidth:     Mov     ah, 0Fh                 ; get screen width
  354.                 Int     10h
  355.                 Mov     al, ah                  ; width was in ah
  356.                 Xor     dh, dh
  357.                 Jmp     DisplayShort
  358.  
  359.  
  360. SysModel:       Push    es                      ; get model indicator
  361.                 Mov     bx, 0F000h              ; save ES; set up ES to
  362.                 Mov     es, bx                  ; point to ROM location
  363.                 Mov     bl, byte ptr es:0FFFEh  ; this is model indicator
  364.                 Pop     es                      ; restore ES
  365.                 Sub     bl, 0F7h                ; subtract offset
  366.                 Mov     [RetVal], bl            ; save for return
  367.                 Shl     bl, 1
  368.                 Xor     bh, bh
  369.                 Cmp     bl, ModelStrLen - ModelString
  370.                 Jbe     SysModel2
  371.                 Xor     bl, bl
  372. SysModel2:      StuffChar [ModelString+bx]      ; display ID
  373.                 StuffChar [(ModelString+1)+bx]
  374.                 Ret
  375.  
  376.  
  377. DosVersion:     Mov     ah, 30h                 ; get DOS version
  378.                 Int     21h
  379.                 Push    ax
  380.                 Call    DisplayVeryShort        ; show major version number
  381.                 StuffChar '.'
  382.                 Pop     ax
  383.                 Xchg    ah, al                  ; and minor version number, too
  384.                 Jmp     DisplayTwoDigs
  385.  
  386.  
  387. BiosVersion:    Push    ds                      ; get BIOS version; save DS
  388.                 Push    si                      ; ... and SI
  389.                 Mov     ax, 0FFFFh              ; set up DS
  390.                 Mov     ds, ax                  ; to point to ROM location
  391.                 Mov     si, 5h
  392.                 Mov     cx, 8                   ; 8 bytes length
  393.                 Mov     ah, 02h
  394. BiosVer2:       Lodsb
  395.                 Call    StuffIt                 ; stuff char
  396.                 Loop    BiosVer2                ; loop for 8 chars
  397.                 Pop     si                      ; restore SI...
  398.                 Pop     ds                      ; and DS
  399.                 Ret
  400.  
  401.  
  402. SwitchChar:     Mov     ax, 3700h               ; get switch character
  403.                 Int     21h
  404.                 Mov     [RetVal], dl            ; save for return
  405.                 StuffChar dl
  406.                 Int     21h
  407.                 Ret
  408.  
  409.  
  410. Author:         Push    si
  411.                 Mov     si, offset Copyright    ; show author's note
  412. Author2:        Lodsb
  413.                 Cmp     al, '$'
  414.                 Je      Author3
  415.                 Call    StuffIt
  416.                 Jmps    Author2
  417. Author3:        Pop     si
  418.                 Ret
  419.  
  420.  
  421. KeyBoard:       Xor     ah, ah                  ; get key from user
  422.                 Int     16h
  423.                 Or      al, al                  ; was it extended key?
  424.                 Je      KeyBoard                ; if so, try again
  425.                 Mov     [RetVal], al            ; save for return
  426.                 Jmp     StuffIt                 ; otherwise echo
  427.  
  428.  
  429. StdInSymbol:    StuffChar '<'                   ; display stdin redir.symbol
  430.                 Mov     [RetVal], '<'           ; save for return
  431.                 Ret
  432.  
  433.  
  434. StdOutSymbol:   StuffChar '>'                   ; display stdout redir.symbol
  435.                 Mov     [RetVal], '>'           ; save for return
  436.                 Ret
  437.  
  438.  
  439. PipeSymbol:     StuffChar '|'                   ; display pipe symbol
  440.                 Mov     [RetVal], '|'           ; save for return
  441.                 Ret
  442.  
  443.  
  444. HexNumber:      Lodsb                           ; display byte given by
  445.                 Cmp     al, Return              ; two hex digits
  446.                 Je      HexEnd
  447.                 Sub     al, '0'                 ; subtract ASCII offset
  448.                 Cmp     al, 9                   ; was that enough?
  449.                 Jbe     Digit1OK                ; if so, skip
  450.                 Sub     al, 7                   ; subtract rest
  451.                 Cmp     al, 0Fh                 ; was that enough?
  452.                 Jbe     Digit1OK                ; if so, skip
  453.                 Sub     al, 'a'-'A'             ; otherwise assume lower-case
  454.  
  455. Digit1OK:       Mov     cl, 4                   ; shift as appropriate
  456.                 ShL     al, cl
  457.                 Mov     dl, al
  458.                 Lodsb                           ; get second digit
  459.                 Cmp     al, Return
  460.                 Je      HexEnd
  461.                 Sub     al, '0'                 ; subtract ASCII offset
  462.                 Cmp     al, 9                   ; was that enough?
  463.                 Jbe     Digit2OK                ; if so, skip
  464.                 Sub     al, 7                   ; subtract rest
  465.                 Cmp     al, 0Fh                 ; was that enough?
  466.                 Jbe     Digit2OK                ; if so, skip
  467.                 Sub     al, 'a'-'A'             ; otherwise assume lower-case
  468.  
  469. Digit2OK:       Or      al, dl                  ; combine digits
  470.                 Mov     [RetVal], al            ; save for return
  471.                 Jmp     StuffIt                 ; and put 'em out
  472.  
  473. HexEnd:         Pop     ax                      ; premature end; pop address
  474.                 Jmp     Done
  475.  
  476.  
  477. CountryInfo:    Mov     ax, 3800h               ; get country info
  478.                 Mov     dx, offset DirString
  479.                 Int     21h
  480.                 Mov     al, bl
  481.                 Jmps    DisplayVeryShort        ; show it
  482.  
  483.  
  484. Currency:       Mov     ax, 3800h               ; get country info
  485.                 Mov     dx, offset DirString
  486.                 Int     21h
  487.                 Mov     ah, [DirString+2]
  488.                 Mov     [RetVal], ah            ; save for return
  489.                 Xor     bx, bx
  490. Curr2:          Mov     al, [(DirString+2)+bx]
  491.                 Or      al, al
  492.                 Je      Curr3
  493.                 Call    StuffIt
  494.                 Inc     bx
  495.                 Jmps    Curr2
  496. Curr3:          Ret
  497.  
  498.  
  499. Thousands:      Mov     cx, 7                   ; prepare to get 1000 sep.
  500.                 Jmps    GetCountry
  501.  
  502.  
  503. Decimal:        Mov     cx, 9                   ; prepare to get decimal sep.
  504.                 Jmps    GetCountry
  505.  
  506.  
  507. DateSep:        Mov     cx, 11                  ; prepare to get date separator
  508.                 Jmps    GetCountry
  509.  
  510.  
  511. TimeSep:        Mov     cx, 13                  ; prepare to get time separator
  512. GetCountry:     Mov     ax, 3800h               ; get country info
  513.                 Mov     dx, offset DirString    ; pointer to buffer
  514.                 Int     21h
  515.                 Mov     bx, cx
  516.                 Mov     al, [DirString+bx]
  517.                 Mov     [RetVal], al            ; save for return
  518.                 Call    StuffIt
  519.                 Ret
  520.  
  521.  
  522. Day:            Mov     al, [DateBuf+3]         ; get day
  523.                 Jmps    DisplayTwoDigs
  524.  
  525.  
  526. Month:          Mov     al, [DateBuf+2]         ; get month
  527.                 Jmps    DisplayTwoDigs
  528.  
  529.  
  530. Year:           Mov     ax, word ptr [DateBuf]  ; get year
  531.                 Jmps    DisplayTwoDigs
  532.  
  533.  
  534. WeekDay:        Mov     al, [DateBuf+4]         ; get weekday
  535.                 Jmps    DisplayVeryShort
  536.  
  537.  
  538. Hour:           Mov     al, [TimeBuf]           ; get hours
  539.                 Jmps    DisplayTwoDigs
  540.  
  541.  
  542. Minute:         Mov     al, [TimeBuf+1]         ; get minutes
  543.                 Jmps    DisplayTwoDigs
  544.  
  545.  
  546. Second:         Mov     al, [TimeBuf+2]         ; get seconds
  547.                 Jmps    DisplayTwoDigs
  548.  
  549.  
  550. CentiSecond:    Mov     al, [TimeBuf+3]         ; get centiseconds
  551.  
  552. DisplayVeryShort: Xor   dh, dh                  ; short number, no min digits
  553.                 Jmps    DisplayShort
  554. DisplayTwoDigs: Mov     dh, 02                  ; display >= 2 digits
  555. DisplayShort:   Xor     ah, ah                  ; output number up to 255
  556.                 Mov     [RetVal], al            ; save for return
  557. DisplayNumber:  Xor     cx, cx                  ; output number up to 2559
  558.                                                 ; dh  is min # of digits
  559.                 Mov     dl, 10                  ; divisor
  560. DispNum2:       Div     dl
  561.                 Push    ax                      ; one digit
  562.                 Inc     cl
  563.                 Xor     ah, ah
  564.                 Or      al, al
  565.                 Jnz     DispNum2                ; loop until we are done
  566.  
  567.                 Cmp     cl, dh                  ; do we have enough digits?
  568.                 Jae     DispNum3                ; if so, skip
  569.                 Push    cx
  570.                 Sub     dh, cl
  571.                 Mov     cl, dh
  572. DispNum2a:      StuffChar '0'                   ; otherwise output leading 0s
  573.                 Loop    DispNum2a
  574.                 Pop     cx
  575.  
  576. DispNum3:       Pop     ax                      ; get back one digit
  577.                 Xchg    ah, al
  578.                 Or      al, '0'                 ; convert to ASCII
  579.                 Call    StuffIt                 ; and display
  580.                 Loop    DispNum3
  581.  
  582.                 Ret
  583.  
  584. StuffIt:        Push    ax                      ; puts char in AL into env
  585.                 Push    bx                      ; string, if room permits
  586.                 Mov     Bl, [OutLine]
  587.                 Cmp     Bl, 7Fh                 ; is there room left?
  588.                 Jae     StuffIt2                ; if not, skip this
  589.                 Inc     Bl
  590.                 Mov     [OutLine], Bl
  591.                 Xor     Bh, Bh
  592.                 Mov     [OutLine+bx], Al
  593. StuffIt2:       Pop     bx
  594.                 Pop     ax
  595.                 Ret
  596.  
  597.  
  598. cseg            ends
  599. end start
  600.