home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / BATCH / DAT13.ZIP / DAT.ASM next >
Encoding:
Assembly Source File  |  1990-10-28  |  27.9 KB  |  724 lines

  1. ;--------------------------------------------------------------------------;
  2. ;  Program:    DAT    .Asm                                                 ;
  3. ;  Purpose:    Displays current date and time.                             ;
  4. ;  Notes:      Compiles under TURBO Assembler, v2.0. Should work on any    ;
  5. ;                 machine running MS-DOS, v2.xx or higher.                 ;
  6. ;  Status:     Released into the public domain. Enjoy! If you use it,      ;
  7. ;                 let me know what you think. You don't have to send       ;
  8. ;                 any money, just comments and suggestions.                ;
  9. ;  Updates:    06-Mar-90, v1.0, GAT                                        ;
  10. ;                 - initial version.                                       ;
  11. ;              13-Mar-90, v1.1, GAT                                        ;
  12. ;                 - added n option to suppress final CR/LF sequence.       ;
  13. ;              19-Mar-90, GAT                                              ;
  14. ;                 - fixed up on-line help message.                         ;
  15. ;              22-Apr-90, v1.2, GAT                                        ;
  16. ;                 - revised most procedures based on work with ASK.        ;
  17. ;              05-May-90, GAT                                              ;
  18. ;                 - fixed bug in handling of non-zero return codes.        ;
  19. ;              12-Jun-90, GAT                                              ;
  20. ;                 - fixed bug in conv_Int2Ascii wrt DI's final value.      ;
  21. ;              08-Jul-90, GAT                                              ;
  22. ;                 - added macros to push/pop registers.                    ;
  23. ;              28-Aug-90, v1.3a, GAT                                       ;
  24. ;                 - put equates and macros in separate files.              ;
  25. ;                 - put common routines in libs.                           ;
  26. ;                 - added equates for date/time separators.                ;
  27. ;--------------------------------------------------------------------------;
  28.  
  29. ;--------------------------------------------------------------------------;
  30. ;  Author:     George A. Theall                                            ;
  31. ;  Phone:      +1 215 662 0558                                             ;
  32. ;  SnailMail:  TifaWARE                                                    ;
  33. ;              506 South 41st St., #3M                                     ;
  34. ;              Philadelphia, PA.  19104   USA                              ;
  35. ;  E-Mail:     GTHEALL@PENNDRLS.UPENN.EDU (Internet)                       ;
  36. ;--------------------------------------------------------------------------;
  37.  
  38. ;--------------------------------------------------------------------------;
  39. ;                          D I R E C T I V E S                             ;
  40. ;--------------------------------------------------------------------------;
  41. DOSSEG
  42. MODEL     tiny
  43.  
  44. IDEAL
  45. LOCALS
  46. JUMPS
  47.  
  48. ;
  49. ; This section comes from D:\ASM\INCLUDE\Equates.Inc.
  50. ;
  51. EOS                 EQU       0              ; terminates strings
  52. BELL                EQU       7
  53. BS                  EQU       8
  54. TAB                 EQU       9
  55. CR                  EQU       13
  56. LF                  EQU       10
  57. ESCAPE              EQU       27             ; nb: ESC is a TASM keyword
  58. SPACE               EQU       ' '
  59. KEY_F1              EQU       3bh
  60. KEY_F2              EQU       3ch
  61. KEY_F3              EQU       3dh
  62. KEY_F4              EQU       3eh
  63. KEY_F5              EQU       3fh
  64. KEY_F6              EQU       40h
  65. KEY_F7              EQU       41h
  66. KEY_F8              EQU       42h
  67. KEY_F9              EQU       43h
  68. KEY_F10             EQU       44h
  69. KEY_HOME            EQU       47h
  70. KEY_UP              EQU       48h
  71. KEY_PGUP            EQU       49h
  72. KEY_LEFT            EQU       4bh
  73. KEY_RIGHT           EQU       4dh
  74. KEY_END             EQU       4fh
  75. KEY_DOWN            EQU       50h
  76. KEY_PGDN            EQU       51h
  77. KEY_INS             EQU       52h
  78. KEY_DEL             EQU       53h
  79. KEY_C_F1            EQU       5eh
  80. KEY_C_F2            EQU       5fh
  81. KEY_C_F3            EQU       60h
  82. KEY_C_F4            EQU       61h
  83. KEY_C_F5            EQU       62h
  84. KEY_C_F6            EQU       63h
  85. KEY_C_F7            EQU       64h
  86. KEY_C_F8            EQU       65h
  87. KEY_C_F9            EQU       66h
  88. KEY_C_F10           EQU       67h
  89. KEY_C_LEFT          EQU       73h
  90. KEY_C_RIGHT         EQU       74h
  91. KEY_C_END           EQU       75h
  92. KEY_C_PGDN          EQU       76h
  93. KEY_C_HOME          EQU       77h
  94. KEY_C_PGUP          EQU       84h
  95. KEY_F11             EQU       85h
  96. KEY_F12             EQU       86h
  97. KEY_C_F11           EQU       89h
  98. KEY_C_F12           EQU       8ah
  99. DOS                 EQU       21h            ; main MSDOS interrupt
  100. STDIN               EQU       0              ; standard input
  101. STDOUT              EQU       1              ; standard output
  102. STDERR              EQU       2              ; error output
  103. STDAUX              EQU       3              ; COM port
  104. STDPRN              EQU       4              ; printer
  105.  
  106. ;
  107. ; This section comes from D:\ASM\INCLUDE\Macros.Inc.
  108. ;
  109. MACRO    Pop_M    RegList                    ;; Pops registers off stack.
  110.    IRP      Reg, <RegList>
  111.       IFIDNI   <Reg>, <flags>
  112.          popf
  113.       ELSE
  114.          pop      Reg
  115.       ENDIF
  116.    ENDM
  117. ENDM
  118. MACRO    Push_M   RegList                    ;; Pushes registers onto stack.
  119.    IRP      Reg, <RegList>
  120.       IFIDNI   <Reg>, <flags>
  121.          pushf
  122.       ELSE
  123.          push     Reg
  124.       ENDIF
  125.    ENDM
  126. ENDM
  127. MACRO    Zero     Reg                        ;; Zeros any register.
  128.          xor      Reg, Reg
  129. ENDM
  130.  
  131.  
  132. ERRH                equ       1              ; errorlevel if help given
  133. DATE_SEP            equ       '/'            ; date separator
  134. TIME_SEP            equ       ':'            ; time separator
  135.  
  136.  
  137. ;--------------------------------------------------------------------------;
  138. ;                        C O D E    S E G M E N T                          ;
  139. ;--------------------------------------------------------------------------;
  140. CODESEG
  141.  
  142. ORG       80h                                ; commandline
  143. LABEL     CmdLen    BYTE
  144.           db        ?
  145. LABEL     CmdLine   BYTE
  146.           db        127 dup (?)
  147.  
  148. ORG       100h                               ; start of .COM file
  149. STARTUPCODE
  150.           jmp       main                     ; skip over data and stack
  151.  
  152. ;--------------------------------------------------------------------------;
  153. ;                               D A T A                                    ;
  154. ;--------------------------------------------------------------------------;
  155. LABEL     ProgName  BYTE
  156.           db        'dat: ', EOS
  157. LABEL     EOL       BYTE
  158.           db        '.', CR, LF, EOS
  159. LABEL     HelpMsg   BYTE
  160.           db        CR, LF
  161.           db        'TifaWARE DAT, v1.3a, ', ??Date
  162.           db        ' - displays the current date and time.', CR, LF
  163.           db        'Usage: dat [-options] [msg]', CR, LF, LF
  164.           db        'Options:', CR, LF
  165.           db        '  -d = display date', CR, LF
  166.           db        '  -n = suppress final newline sequence', CR, LF
  167.           db        '  -t = display time', CR, LF
  168.           db        '  -? = display this help message', CR, LF, LF
  169.           db        'msg is an optional message to display before '
  170.           db        'the date or time.', CR, LF, EOS
  171. LABEL     Err1Msg   BYTE
  172.           db        'illegal option -- '
  173. LABEL     OptCh     BYTE
  174.           db        ?
  175.           db        EOS
  176. LABEL     TwoDigits BYTE                     ; space for two digits
  177.           db        2 dup (?), EOS
  178.  
  179. SwitCh    db        '-'                      ; char introducing options
  180. HFlag     db        0                        ; flag for on-line help
  181. DFlag     db        0                        ; flag for displaying date
  182. NFlag     db        0                        ; flag for suppressing CR/LF
  183. TFlag     db        0                        ; flag for displaying time
  184. MsgLen    db        0                        ; length of message text
  185. MsgTxt    dw        ?                        ; near pointer to message text
  186. RCode     db        0                        ; program return code
  187.  
  188.  
  189. ;--------------------------------------------------------------------------;
  190. ;                          L O C A L   S T A C K                           ;
  191. ;--------------------------------------------------------------------------;
  192.           db        16 dup("STACK   ")       ; 128 bytes for local stack
  193. StackTop  =         $
  194.  
  195.  
  196. ;--------------------------------------------------------------------------;
  197. ;                           P R O C E D U R E S                            ;
  198. ;--------------------------------------------------------------------------;
  199. ;----  put_TwoDigits  -----------------------------------------------------;
  200. ;  Purpose:    Displays a number between 0 and 99 on STDOUT with a leading ;
  201. ;                   0 as necessary.                                        ;
  202. ;  Notes:      No validity checks are done.                                ;
  203. ;  Entry:      AL = number to display.                                     ;
  204. ;  Exit:       n/a                                                         ;
  205. ;  Calls:      utoa, putchar, fputs                                        ;
  206. ;  Changes:    [TwoDigits]                                                 ;
  207. ;--------------------------------------------------------------------------;
  208. PROC put_TwoDigits
  209.  
  210.           Push_M    <ax, bx, dx, di>
  211.           Zero      ah
  212.           mov       bx, STDOUT
  213.           mov       di, OFFSET TwoDigits
  214.           call      utoa                     ; treat it as unsigned int
  215.           cmp       al, 9                    ; need a leading 0?
  216.           ja        SHORT @@WriteIt
  217.           mov       dl, '0'
  218.           call      putchar
  219. @@WriteIt:
  220.           mov       dx, di
  221.           call      fputs
  222.           Pop_M     <di, dx, bx, ax>
  223.  
  224.           ret
  225. ENDP put_TwoDigits
  226.  
  227.  
  228. ;----  skip_Spaces  -------------------------------------------------------;
  229. ;  Purpose:    Skips past spaces in a string.                              ;
  230. ;  Notes:      Scanning stops with either a non-space *OR* CX = 0.         ;
  231. ;  Entry:      DS:SI = start of string to scan.                            ;
  232. ;  Exit:       AL = next non-space character,                              ;
  233. ;              CX is adjusted as necessary,                                ;
  234. ;              DS:SI = pointer to next non-space.                          ;
  235. ;  Calls:      none                                                        ;
  236. ;  Changes:    AL, CX, SI                                                  ;
  237. ;--------------------------------------------------------------------------;
  238. PROC skip_Spaces
  239.  
  240.           jcxz      SHORT @@Fin
  241. @@NextCh:
  242.           lodsb
  243.           cmp       al, ' '
  244.           loopz     @@NextCh
  245.           jz        SHORT @@Fin              ; CX = 0; don't adjust
  246.  
  247.           inc       cx                       ; adjust counters if cx > 0
  248.           dec       si
  249.  
  250. @@Fin:
  251.           ret
  252. ENDP skip_Spaces
  253.  
  254.  
  255. ;----  get_Opt  -----------------------------------------------------------;
  256. ;  Purpose:    Get a commandline option.                                   ;
  257. ;  Notes:      none                                                        ;
  258. ;  Entry:      AL = option character,                                      ;
  259. ;  Exit:       n/a                                                         ;
  260. ;  Calls:      tolower, errmsg                                             ;
  261. ;  Changes:    AX, DX,                                                     ;
  262. ;              [OptCh], [HFlag], [DFlag], [NFlag], [TFlag],                ;
  263. ;--------------------------------------------------------------------------;
  264. PROC get_Opt
  265.  
  266.           mov       [OptCh], al              ; save for later
  267.           call      tolower                  ; use only lowercase in cmp.
  268.           cmp       al, 'd'
  269.           jz        SHORT @@OptD
  270.           cmp       al, 'n'
  271.           jz        SHORT @@OptN
  272.           cmp       al, 't'
  273.           jz        SHORT @@OptT
  274.           cmp       al, '?'
  275.           jz        SHORT @@OptH
  276.           mov       dx, OFFSET Err1Msg       ; unrecognized option
  277.           call      errmsg                   ; then *** DROP THRU *** to OptH
  278.  
  279. ;
  280. ; Various possible options.
  281. ;
  282. @@OptH:
  283.           mov       [HFlag], 1               ; set help flag
  284.           jmp       SHORT @@Fin
  285.  
  286. @@OptD:
  287.           mov       [DFlag], 1               ; display date
  288.           jmp       SHORT @@Fin
  289.  
  290. @@OptN:
  291.           mov       [NFlag], 1               ; no final CR/LF
  292.           jmp       SHORT @@Fin
  293.  
  294. @@OptT:
  295.           mov       [TFlag], 1               ; display time
  296.  
  297. @@Fin:
  298.           ret
  299. ENDP get_Opt
  300.  
  301.  
  302. ;----  get_Arg  -----------------------------------------------------------;
  303. ;  Purpose:    Gets a non-option from the set of commandline arguments.    ;
  304. ;  Notes:      Anything left on the commandline is user's message text.    ;
  305. ;  Entry:      CX = count of characters left in commandline,               ;
  306. ;              DS:SI = pointer to argument to process.                     ;
  307. ;  Exit:       CX = zero                                                   ;
  308. ;              DS:SI = points to CR after commandline.                     ;
  309. ;  Calls:      none                                                        ;
  310. ;  Changes:    CX, SI                                                      ;
  311. ;              [MsgLen], [MsgTxt]                                          ;
  312. ;--------------------------------------------------------------------------;
  313. PROC get_Arg
  314.  
  315.           mov       [MsgLen], cl             ; for safekeeping
  316.           mov       [MsgTxt], si
  317.           add       si, cx                   ; adjust so nothing's left
  318.           Zero      cl
  319.           mov       [BYTE PTR si], EOS       ; finish off string
  320.  
  321.           ret
  322. ENDP get_Arg
  323.  
  324.  
  325. ;----  process_CmdLine  ---------------------------------------------------;
  326. ;  Purpose:    Processes commandline arguments.                            ;
  327. ;  Notes:      A switch character by itself is ignored.                    ;
  328. ;              No arguments whatsoever causes help flag to be set.         ;
  329. ;  Entry:      n/a                                                         ;
  330. ;  Exit:       n/a                                                         ;
  331. ;  Calls:      skip_Spaces, get_Opt, get_Arg                               ;
  332. ;  Changes:    AX, CX, SI,                                                 ;
  333. ;              DX (get_Opt),                                               ;
  334. ;              [DFlag], [TFlag],                                           ;
  335. ;              [OptCh], [NFlag] (get_Opt),                                 ;
  336. ;              [MsgLen], [MsgTxt] (get_Arg),                               ;
  337. ;              Direction flag is cleared.                                  ;
  338. ;--------------------------------------------------------------------------;
  339. PROC process_CmdLine
  340.  
  341.           cld                                ; forward, march!
  342.           Zero      ch, ch
  343.           mov       cl, [CmdLen]             ; length of commandline
  344.           mov       si, OFFSET CmdLine       ; offset to start of commandline
  345.  
  346.           call      skip_Spaces              ; check if any args supplied
  347.           or        cl, cl
  348.           jnz       SHORT @@ArgLoop          ;   yep
  349.           mov       [DFlag], 1               ;   nope, so display date ...
  350.           mov       [TFlag], 1               ;     and time
  351.           jmp       SHORT @@Fin
  352.  
  353. ;
  354. ; For each blank-delineated argument on the commandline...
  355. ;
  356. @@ArgLoop:
  357.           lodsb                              ; next character
  358.           dec       cl
  359.           cmp       al, [SwitCh]             ; is it the switch character?
  360.           jnz       SHORT @@NonOpt           ;   no
  361.  
  362. ;
  363. ; Isolate each option and process it. Stop when a space is reached.
  364. ;
  365. @@OptLoop:
  366.           jcxz      SHORT @@Fin              ; abort if nothing left
  367.           lodsb
  368.           dec       cl
  369.           cmp       al, ' '
  370.           jz        SHORT @@NextArg          ; abort when space reached
  371.           call      get_Opt
  372.           jmp       @@OptLoop
  373.  
  374. ;
  375. ; Process the current argument, which is *not* an option.
  376. ; Then, *drop thru* to advance to next argument.
  377. ;
  378. @@NonOpt:
  379.           dec       si                       ; back up one character
  380.           inc       cl
  381.           call      get_Arg
  382.  
  383. ;
  384. ; Skip over spaces until next argument is reached.
  385. ;
  386. @@NextArg:
  387.           call      skip_Spaces
  388.           or        cl, cl
  389.           jnz       @@ArgLoop
  390.  
  391. @@Fin:
  392.           ret
  393. ENDP process_CmdLine
  394.  
  395.  
  396. ;--------------------------------------------------------------------------;
  397. ;                         E N T R Y   P O I N T                            ;
  398. ;--------------------------------------------------------------------------;
  399. ;----  main  --------------------------------------------------------------;
  400. ;  Purpose:    Main section of program.                                    ;
  401. ;  Notes:      none                                                        ;
  402. ;  Entry:      Arguments as desired                                        ;
  403. ;  Exit:       Return code as follows:                                     ;
  404. ;                   0 => program ran successfully                          ;
  405. ;                   1 => on-line help requested                            ;
  406. ;  Calls:      process_CmdLine, fputs, putchar, getdate, put_TwoDigits,    ;
  407. ;                   gettime                                                ;
  408. ;  Changes:    n/a                                                         ;
  409. ;--------------------------------------------------------------------------;
  410. main:
  411.           mov       sp, OFFSET StackTop      ; set up local stack
  412.  
  413. ;
  414. ; Process commandline arguments. If the variable HFlag is set, then
  415. ; on-line help is displayed and the program immediately terminates.
  416. ;
  417.           call      process_CmdLine          ; process commandline args
  418.  
  419.           cmp       [HFlag], 0               ; is help needed?
  420.           jz        SHORT @@NoHelp           ;   no
  421.           mov       [RCode], ERRH            ;   yes, so set return code
  422.           mov       bx, STDERR
  423.           mov       dx, OFFSET HelpMsg       ;     point to help message
  424.           call      fputs                    ;     display it
  425.           jmp       SHORT @@Fin              ;     and jump to end of program
  426.  
  427. ;
  428. ; Display any message from commandline then get keypress from user.
  429. ;
  430. @@NoHelp:
  431.           mov       bx, STDOUT               ; everything to stdout
  432.           cmp       [MsgLen], 0              ; anything to print out?
  433.           jz        SHORT @@Date?            ;   nope
  434.           mov       dx, [MsgTxt]             ; display message text
  435.           call      fputs
  436.           mov       dl, ' '                  ; and a space
  437.           call      putchar
  438.  
  439. @@Date?:
  440.           cmp       [DFlag], 0
  441.           jz        SHORT @@Time?
  442.  
  443.           call      getdate
  444.           mov       al, dh                   ; dh = month
  445.           call      put_TwoDigits
  446.           mov       al, dl                   ; dl = day
  447.           mov       dl, DATE_SEP             ; now we can use dl for DATE_SEP
  448.           call      putchar
  449.           call      put_TwoDigits
  450.           call      putchar                  ; dl still holds DATE_SEP
  451.           mov       ax, cx                   ; cx = year
  452.           sub       ax, 1900                 ; assume 20th century
  453.           call      put_TwoDigits
  454.           mov       dl, ' '
  455.           call      putchar
  456.  
  457. @@Time?:
  458.           cmp       [TFlag], 0               ; display time?
  459.           jz        SHORT @@FinalEOL?        ;   no
  460.  
  461.           call      gettime
  462.           mov       al, ch                   ; ch = hour
  463.           call      put_TwoDigits
  464.           mov       dl, TIME_SEP
  465.           call      putchar
  466.           mov       al, cl                   ; cl = minutes
  467.           call      put_TwoDigits
  468.  
  469. @@FinalEOL?:
  470.           cmp       [NFlag], 0               ; suppress final CR/LF?
  471.           jnz       SHORT @@Fin              ;   no
  472.  
  473.           mov       dx, OFFSET EOL+1
  474.           call      fputs
  475.  
  476. ;
  477. ; Ok, let's terminate the program and exit with proper return code.
  478. ;
  479. @@Fin:
  480.           mov       al, [RCode]
  481.           mov       ah, 4ch
  482.           int       DOS
  483.  
  484. EVEN
  485. ;-------------------------------------------------------------------------;
  486. ;  Purpose:    Gets current system date, based on DOS's internal clock.
  487. ;  Notes:      none
  488. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  489. ;  Entry:      n/a
  490. ;  Exit:       AL = day of week (0 = Sunday)
  491. ;              DL = day (1 to 31)
  492. ;              DH = month (1 to 12)
  493. ;              CX = year (1980 to 2099)
  494. ;  Calls:      none
  495. ;  Changes:    AX, CX, DX
  496. ;-------------------------------------------------------------------------;
  497. PROC getdate
  498.  
  499.    mov      ah, 2ah                       ; MS-DOS get system date function
  500.    int      DOS
  501.    ret
  502.  
  503. ENDP getdate
  504.  
  505.  
  506. EVEN
  507. ;-------------------------------------------------------------------------;
  508. ;  Purpose:    Gets current system time, based on DOS's internal clock.
  509. ;  Notes:      none
  510. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  511. ;  Entry:      n/a
  512. ;  Exit:       CL = minutes (0 - 59)
  513. ;              CH = hour (0 - 23)
  514. ;              DL = hundredths of seconds (0 - 99)
  515. ;              DH = seconds (0 - 59)
  516. ;  Calls:      none
  517. ;  Changes:    CX, DX
  518. ;-------------------------------------------------------------------------;
  519. PROC gettime
  520.  
  521.    push     ax
  522.    mov      ah, 2ch                       ; MS-DOS get system time function
  523.    int      DOS
  524.    pop      ax
  525.    ret
  526.  
  527. ENDP gettime
  528.  
  529.  
  530. EVEN
  531. ;-------------------------------------------------------------------------;
  532. ;  Purpose:    Writes an ASCIIZ string to specified device.
  533. ;  Notes:      A zero-length string doesn't seem to cause problems when
  534. ;                 this output function is used.
  535. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  536. ;  Entry:      BX = device handle,
  537. ;              DS:DX = pointer to string.
  538. ;  Exit:       Carry flag set if EOS wasn't found or handle is invalid.
  539. ;  Calls:      strlen
  540. ;  Changes:    none
  541. ;-------------------------------------------------------------------------;
  542. PROC fputs
  543.  
  544. IF @DataSize EQ 0
  545.    Push_M   <ax, cx, di>
  546. ELSE
  547.    Push_M   <ax, cx, di, es>
  548.    mov      ax, ds
  549.    mov      es, ax
  550. ENDIF
  551.    mov      di, dx
  552.    call     strlen                        ; set CX = length of string
  553.    jc       SHORT @@Fin                   ; abort if problem finding end
  554.    mov      ah, 40h                       ; MS-DOS raw output function
  555.    int      DOS
  556. @@Fin:
  557. IF @DataSize EQ 0
  558.    Pop_M    <di, cx, ax>
  559. ELSE
  560.    Pop_M    <es, di, cx, ax>
  561. ENDIF
  562.    ret
  563.  
  564. ENDP fputs
  565.  
  566.  
  567. EVEN
  568. ;-------------------------------------------------------------------------;
  569. ;  Purpose:    Writes a character to STDOUT device.
  570. ;  Notes:      none
  571. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  572. ;  Entry:      DL = character to display.
  573. ;  Exit:       n/a
  574. ;  Calls:      none
  575. ;  Changes:    none
  576. ;-------------------------------------------------------------------------;
  577. PROC putchar
  578.  
  579.    push     ax
  580.    mov      ah, 2
  581.    int      DOS
  582.    pop      ax
  583.    ret
  584.  
  585. ENDP putchar
  586.  
  587.  
  588. EVEN
  589. ;-------------------------------------------------------------------------;
  590. ;  Purpose:    Writes an error message to stderr.
  591. ;  Notes:      none
  592. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  593. ;  Entry:      DS:DX = pointer to error message.
  594. ;  Exit:       n/a
  595. ;  Calls:      fputs
  596. ;  Changes:    none
  597. ;-------------------------------------------------------------------------;
  598. PROC errmsg
  599.  
  600.    Push_M   <bx, dx>
  601.    push     dx                            ; save again calling parameters
  602.    mov      bx, STDERR
  603.    mov      dx, OFFSET ProgName           ; display program name
  604.    call     fputs
  605.    pop      dx                            ; recover calling parameters
  606.    call     fputs                         ; display error message
  607.    mov      dx, OFFSET EOL
  608.    call     fputs
  609.    Pop_M    <dx, bx>
  610.    ret
  611.  
  612. ENDP errmsg
  613.  
  614.  
  615. EVEN
  616. ;-------------------------------------------------------------------------;
  617. ;  Purpose:    Converts an *unsigned* integer in range [0, 65535] to
  618. ;              an ASCIIZ string of digits.
  619. ;  Notes:      No checks are made to ensure storage area is big enough.
  620. ;              A terminating null is added.
  621. ;  Requires:   8086-class CPU.
  622. ;  Entry:      AX = unsigned integer value,
  623. ;              ES:DI = pointer to string storage area.
  624. ;  Exit:       ES:DI = pointer to start of string.
  625. ;  Calls:      none
  626. ;  Changes:    DI
  627. ;-------------------------------------------------------------------------;
  628. PROC utoa
  629.  
  630.    Push_M   <ax, bx, cx, dx, di>
  631.    mov      bx, 10                        ; conversion factor
  632.    Zero     cx                            ; track # digits in string
  633.  
  634. @@NewDigit:                               ; for each character
  635.    Zero     dx                            ; dx:ax is dividend so make dx 0
  636.    div      bx                            ; ax = dx:ax / 10
  637.    push     dx                            ; dx = dx:ax mod 10
  638.    inc      cl                            ; one more digit processed
  639.    or       ax, ax                        ; anything left?
  640.    jnz      @@NewDigit
  641.  
  642. @@NextChar:                               ; for each power of ten
  643.    pop      ax
  644.    add      al, '0'
  645.    mov      [BYTE PTR di], al
  646.    inc      di
  647.    loop     @@NextChar
  648.    mov      [BYTE PTR di], EOS            ; don't forget to end it!
  649.  
  650.    Pop_M    <di, dx, cx, bx, ax>
  651.    ret
  652.  
  653. ENDP utoa
  654.  
  655.  
  656. EVEN
  657. ;-------------------------------------------------------------------------;
  658. ;  Purpose:    Converts character to lowercase.
  659. ;  Notes:      none
  660. ;  Requires:   8086-class CPU.
  661. ;  Entry:      AL = character to be converted.
  662. ;  Exit:       AL = converted character.
  663. ;  Calls:      none
  664. ;  Changes:    AL
  665. ;              flags
  666. ;-------------------------------------------------------------------------;
  667. PROC tolower
  668.  
  669.    cmp      al, 'A'                       ; if < 'A' then done
  670.    jb       SHORT @@Fin
  671.    cmp      al, 'Z'                       ; if > 'Z' then done
  672.    ja       SHORT @@Fin
  673.    or       al, 20h                       ; make it lowercase
  674. @@Fin:
  675.    ret
  676.  
  677. ENDP tolower
  678.  
  679.  
  680. EVEN
  681. ;-------------------------------------------------------------------------;
  682. ;  Purpose:    Calculates length of an ASCIIZ string.
  683. ;  Notes:      Terminal char is _not_ included in the count.
  684. ;  Requires:   8086-class CPU.
  685. ;  Entry:      ES:DI = pointer to string.
  686. ;  Exit:       CX = length of string,
  687. ;              cf = 0 and zf = 1 if EOS found,
  688. ;              cf = 1 and zf = 0 if EOS not found within segment.
  689. ;  Calls:      none
  690. ;  Changes:    CX,
  691. ;              flags
  692. ;-------------------------------------------------------------------------;
  693. PROC strlen
  694.  
  695.    Push_M   <ax, di, flags>
  696.    cld                                    ; scan forward only
  697.    mov      al, EOS                       ; character to search for
  698.    mov      cx, di                        ; where are we now
  699.    not      cx                            ; what's left in segment - 1
  700.    push     cx                            ; save char count
  701.    repne    scasb
  702.    je       SHORT @@Done
  703.    scasb                                  ; test final char
  704.    dec      cx                            ; avoids trouble with "not" below
  705.  
  706. @@Done:
  707.    pop      ax                            ; get original count
  708.    sub      cx, ax                        ; subtract current count
  709.    not      cx                            ; and invert it
  710.    popf                                   ; restore df
  711.    dec      di
  712.    cmp      [BYTE PTR es:di], EOS
  713.    je       SHORT @@Fin                   ; cf = 0 if equal
  714.    stc                                    ; set cf => error
  715.  
  716. @@Fin:
  717.    Pop_M    <di, ax>
  718.    ret
  719.  
  720. ENDP strlen
  721.  
  722.  
  723. END
  724.