home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / datetime / dat.asm next >
Assembly Source File  |  1991-11-10  |  34KB  |  909 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. ;              12-Oct-91, v1.3b, GAT                                       ;
  28. ;                 - revised include file names.                            ;
  29. ;                 - replaced references to Push_M and Pop_M macros with    ;
  30. ;                    calls to push and pop.                                ;
  31. ;                 - removed local stack: it's not necessary.               ;
  32. ;--------------------------------------------------------------------------;
  33.  
  34. ;--------------------------------------------------------------------------;
  35. ;  Author:     George A. Theall                                            ;
  36. ;  Phone:      +1 215 662 0558                                             ;
  37. ;  SnailMail:  TifaWARE                                                    ;
  38. ;              506 South 41st St., #3M                                     ;
  39. ;              Philadelphia, PA.  19104   USA                              ;
  40. ;  E-Mail:     theall@gdalsrv.sas.upenn.edu (Internet)                     ;
  41. ;--------------------------------------------------------------------------;
  42.  
  43. ;--------------------------------------------------------------------------;
  44. ;                          D I R E C T I V E S                             ;
  45. ;--------------------------------------------------------------------------;
  46. DOSSEG
  47. MODEL     tiny
  48.  
  49. IDEAL
  50. LOCALS
  51. JUMPS
  52.  
  53. ;
  54. ; This section comes from Misc.Inc.
  55. ;
  56. @16BIT              EQU       (@CPU AND 8) EQ 0
  57. @32BIT              EQU       (@CPU AND 8)
  58. MACRO    ZERO     RegList                    ;; Zeros registers
  59.    IRP      Reg, <RegList>
  60.          xor      Reg, Reg
  61.    ENDM
  62. ENDM
  63.  
  64. ;
  65. ; This section comes from DOS.Inc.
  66. ;
  67. BELL                EQU       7
  68. BS                  EQU       8
  69. TAB                 EQU       9
  70. CR                  EQU       13
  71. LF                  EQU       10
  72. ESCAPE              EQU       27             ; nb: ESC is a TASM keyword
  73. SPACE               EQU       ' '
  74. KEY_F1              EQU       3bh
  75. KEY_F2              EQU       3ch
  76. KEY_F3              EQU       3dh
  77. KEY_F4              EQU       3eh
  78. KEY_F5              EQU       3fh
  79. KEY_F6              EQU       40h
  80. KEY_F7              EQU       41h
  81. KEY_F8              EQU       42h
  82. KEY_F9              EQU       43h
  83. KEY_F10             EQU       44h
  84. KEY_HOME            EQU       47h
  85. KEY_UP              EQU       48h
  86. KEY_PGUP            EQU       49h
  87. KEY_LEFT            EQU       4bh
  88. KEY_RIGHT           EQU       4dh
  89. KEY_END             EQU       4fh
  90. KEY_DOWN            EQU       50h
  91. KEY_PGDN            EQU       51h
  92. KEY_INS             EQU       52h
  93. KEY_DEL             EQU       53h
  94. KEY_C_F1            EQU       5eh
  95. KEY_C_F2            EQU       5fh
  96. KEY_C_F3            EQU       60h
  97. KEY_C_F4            EQU       61h
  98. KEY_C_F5            EQU       62h
  99. KEY_C_F6            EQU       63h
  100. KEY_C_F7            EQU       64h
  101. KEY_C_F8            EQU       65h
  102. KEY_C_F9            EQU       66h
  103. KEY_C_F10           EQU       67h
  104. KEY_C_LEFT          EQU       73h
  105. KEY_C_RIGHT         EQU       74h
  106. KEY_C_END           EQU       75h
  107. KEY_C_PGDN          EQU       76h
  108. KEY_C_HOME          EQU       77h
  109. KEY_C_PGUP          EQU       84h
  110. KEY_F11             EQU       85h
  111. KEY_F12             EQU       86h
  112. KEY_C_F11           EQU       89h
  113. KEY_C_F12           EQU       8ah
  114. DOS                 EQU       21h            ; main MSDOS interrupt
  115. STDIN               EQU       0              ; standard input
  116. STDOUT              EQU       1              ; standard output
  117. STDERR              EQU       2              ; error output
  118. STDAUX              EQU       3              ; COM port
  119. STDPRN              EQU       4              ; printer
  120. TSRMAGIC            EQU       424bh          ; magic number
  121. STRUC     ISR
  122.           Entry     DW        10EBh          ; short jump ahead 16 bytes
  123.           OldISR    DD        ?              ; next ISR in chain
  124.           Sig       DW        TSRMAGIC       ; magic number
  125.           EOIFlag   DB        ?              ; 0 (80) if soft(hard)ware int
  126.           Reset     DW        ?              ; short jump to hardware reset
  127.           Reserved  DB        7 dup (0)
  128. ENDS
  129. STRUC     ISRHOOK
  130.           Vector    DB        ?              ; vector hooked
  131.           Entry     DW        ?              ; offset of TSR entry point
  132. ENDS
  133. STRUC     TSRSIG
  134.           Company   DB        8 dup (" ")    ; blank-padded company name
  135.           Product   DB        8 dup (" ")    ; blank-padded product name
  136.           Desc      DB        64 dup (0)     ; ASCIIZ product description
  137. ENDS
  138. GLOBAL at : PROC
  139. GLOBAL errmsg : PROC
  140.    GLOBAL ProgName : BYTE                    ; needed for errmsg()
  141.    GLOBAL EOL : BYTE                         ; ditto
  142. GLOBAL fgetc : PROC
  143. GLOBAL fputc : PROC
  144. GLOBAL fputs : PROC
  145. GLOBAL getchar : PROC
  146. GLOBAL getdate : PROC
  147. GLOBAL getswtch : PROC
  148. GLOBAL gettime : PROC
  149. GLOBAL getvdos : PROC
  150. GLOBAL getvect : PROC
  151. GLOBAL isatty : PROC
  152. GLOBAL kbhit : PROC
  153. GLOBAL pause : PROC
  154. GLOBAL putchar : PROC
  155. GLOBAL setvect : PROC
  156. GLOBAL sleep : PROC
  157. GLOBAL find_NextISR : PROC
  158. GLOBAL find_PrevISR : PROC
  159. GLOBAL hook_ISR : PROC
  160. GLOBAL unhook_ISR : PROC
  161. GLOBAL free_Env : PROC
  162. GLOBAL fake_Env : PROC
  163. GLOBAL check_ifInstalled : PROC
  164. GLOBAL install_TSR : PROC
  165. GLOBAL remove_TSR : PROC
  166.  
  167. ;
  168. ; This section comes from Math.Inc.
  169. ;
  170. GLOBAL atoi : PROC
  171. GLOBAL atou : PROC
  172. GLOBAL utoa : PROC
  173.  
  174. ;
  175. ; This section comes from String.Inc.
  176. ;
  177. EOS                 EQU       0              ; terminates strings
  178. GLOBAL isdigit : PROC
  179. GLOBAL islower : PROC
  180. GLOBAL isupper : PROC
  181. GLOBAL iswhite : PROC
  182. GLOBAL memcmp : PROC
  183. GLOBAL strchr : PROC
  184. GLOBAL strcmp : PROC
  185. GLOBAL strlen : PROC
  186. GLOBAL tolower : PROC
  187. GLOBAL toupper : PROC
  188.  
  189.  
  190. VERSION   equ       '1.3b'                   ; current version of program
  191. ERRH      equ       1                        ; errorlevel if help given
  192. DATE_SEP  equ       '/'                      ; date separator
  193. TIME_SEP  equ       ':'                      ; time separator
  194.  
  195.  
  196. ;--------------------------------------------------------------------------;
  197. ;                        C O D E    S E G M E N T                          ;
  198. ;--------------------------------------------------------------------------;
  199. CODESEG
  200.  
  201. ORG       80h                                ; commandline
  202. LABEL     CmdLen    BYTE
  203.           db        ?
  204. LABEL     CmdLine   BYTE
  205.           db        127 dup (?)
  206.  
  207. ORG       100h                               ; start of .COM file
  208. STARTUPCODE
  209.           jmp       main                     ; skip over data and stack
  210.  
  211. ;--------------------------------------------------------------------------;
  212. ;                               D A T A                                    ;
  213. ;--------------------------------------------------------------------------;
  214. LABEL     ProgName  BYTE
  215.           db        'dat: ', EOS
  216. LABEL     EOL       BYTE
  217.           db        '.', CR, LF, EOS
  218. LABEL     HelpMsg   BYTE
  219.           db        CR, LF
  220.           db        'TifaWARE DAT, v', VERSION, ', ', ??Date
  221.           db        ' - displays the current date and time.', CR, LF
  222.           db        'Usage: dat [-options] [msg]', CR, LF, LF
  223.           db        'Options:', CR, LF
  224.           db        '  -d = display date', CR, LF
  225.           db        '  -n = suppress final newline sequence', CR, LF
  226.           db        '  -t = display time', CR, LF
  227.           db        '  -? = display this help message', CR, LF, LF
  228.           db        'msg is an optional message to display before '
  229.           db        'the date or time.', CR, LF, EOS
  230. LABEL     Err1Msg   BYTE
  231.           db        'illegal option -- '
  232. LABEL     OptCh     BYTE
  233.           db        ?
  234.           db        EOS
  235. LABEL     TwoDigits BYTE                     ; space for two digits
  236.           db        2 dup (?), EOS
  237.  
  238. SwitCh    db        '-'                      ; char introducing options
  239. HFlag     db        0                        ; flag for on-line help
  240. DFlag     db        0                        ; flag for displaying date
  241. NFlag     db        0                        ; flag for suppressing CR/LF
  242. TFlag     db        0                        ; flag for displaying time
  243. MsgLen    db        0                        ; length of message text
  244. MsgTxt    dw        ?                        ; near pointer to message text
  245. RCode     db        0                        ; program return code
  246.  
  247.  
  248. ;--------------------------------------------------------------------------;
  249. ;                           P R O C E D U R E S                            ;
  250. ;--------------------------------------------------------------------------;
  251. ;----  put_TwoDigits  -----------------------------------------------------;
  252. ;  Purpose:    Displays a number between 0 and 99 on STDOUT with a leading ;
  253. ;                   0 as necessary.                                        ;
  254. ;  Notes:      No validity checks are done.                                ;
  255. ;  Entry:      AL = number to display.                                     ;
  256. ;  Exit:       n/a                                                         ;
  257. ;  Calls:      utoa, putchar, fputs                                        ;
  258. ;  Changes:    [TwoDigits]                                                 ;
  259. ;--------------------------------------------------------------------------;
  260. PROC put_TwoDigits
  261.  
  262.           push      ax bx dx di
  263.           ZERO      ah
  264.           mov       bx, STDOUT
  265.           mov       di, OFFSET TwoDigits
  266.           call      utoa                     ; treat it as unsigned int
  267.           cmp       al, 9                    ; need a leading 0?
  268.           ja        SHORT @@WriteIt
  269.           mov       dl, '0'
  270.           call      putchar
  271. @@WriteIt:
  272.           mov       dx, di
  273.           call      fputs
  274.           pop       di dx bx ax
  275.  
  276.           ret
  277. ENDP put_TwoDigits
  278.  
  279.  
  280. ;----  skip_Spaces  -------------------------------------------------------;
  281. ;  Purpose:    Skips past spaces in a string.                              ;
  282. ;  Notes:      Scanning stops with either a non-space *OR* CX = 0.         ;
  283. ;  Entry:      DS:SI = start of string to scan.                            ;
  284. ;  Exit:       AL = next non-space character,                              ;
  285. ;              CX is adjusted as necessary,                                ;
  286. ;              DS:SI = pointer to next non-space.                          ;
  287. ;  Calls:      none                                                        ;
  288. ;  Changes:    AL, CX, SI                                                  ;
  289. ;--------------------------------------------------------------------------;
  290. PROC skip_Spaces
  291.  
  292.           jcxz      SHORT @@Fin
  293. @@NextCh:
  294.           lodsb
  295.           cmp       al, ' '
  296.           loopz     @@NextCh
  297.           jz        SHORT @@Fin              ; CX = 0; don't adjust
  298.  
  299.           inc       cx                       ; adjust counters if cx > 0
  300.           dec       si
  301.  
  302. @@Fin:
  303.           ret
  304. ENDP skip_Spaces
  305.  
  306.  
  307. ;----  get_Opt  -----------------------------------------------------------;
  308. ;  Purpose:    Get a commandline option.                                   ;
  309. ;  Notes:      none                                                        ;
  310. ;  Entry:      AL = option character,                                      ;
  311. ;  Exit:       n/a                                                         ;
  312. ;  Calls:      tolower, errmsg                                             ;
  313. ;  Changes:    AX, DX,                                                     ;
  314. ;              [OptCh], [HFlag], [DFlag], [NFlag], [TFlag],                ;
  315. ;--------------------------------------------------------------------------;
  316. PROC get_Opt
  317.  
  318.           mov       [OptCh], al              ; save for later
  319.           call      tolower                  ; use only lowercase in cmp.
  320.           cmp       al, 'd'
  321.           jz        SHORT @@OptD
  322.           cmp       al, 'n'
  323.           jz        SHORT @@OptN
  324.           cmp       al, 't'
  325.           jz        SHORT @@OptT
  326.           cmp       al, '?'
  327.           jz        SHORT @@OptH
  328.           mov       dx, OFFSET Err1Msg       ; unrecognized option
  329.           call      errmsg                   ; then *** DROP THRU *** to OptH
  330.  
  331. ;
  332. ; Various possible options.
  333. ;
  334. @@OptH:
  335.           mov       [HFlag], 1               ; set help flag
  336.           jmp       SHORT @@Fin
  337.  
  338. @@OptD:
  339.           mov       [DFlag], 1               ; display date
  340.           jmp       SHORT @@Fin
  341.  
  342. @@OptN:
  343.           mov       [NFlag], 1               ; no final CR/LF
  344.           jmp       SHORT @@Fin
  345.  
  346. @@OptT:
  347.           mov       [TFlag], 1               ; display time
  348.  
  349. @@Fin:
  350.           ret
  351. ENDP get_Opt
  352.  
  353.  
  354. ;----  get_Arg  -----------------------------------------------------------;
  355. ;  Purpose:    Gets a non-option from the set of commandline arguments.    ;
  356. ;  Notes:      Anything left on the commandline is user's message text.    ;
  357. ;  Entry:      CX = count of characters left in commandline,               ;
  358. ;              DS:SI = pointer to argument to process.                     ;
  359. ;  Exit:       CX = zero                                                   ;
  360. ;              DS:SI = points to CR after commandline.                     ;
  361. ;  Calls:      none                                                        ;
  362. ;  Changes:    CX, SI                                                      ;
  363. ;              [MsgLen], [MsgTxt]                                          ;
  364. ;--------------------------------------------------------------------------;
  365. PROC get_Arg
  366.  
  367.           mov       [MsgLen], cl             ; for safekeeping
  368.           mov       [MsgTxt], si
  369.           add       si, cx                   ; adjust so nothing's left
  370.           ZERO      cl
  371.           mov       [BYTE PTR si], EOS       ; finish off string
  372.  
  373.           ret
  374. ENDP get_Arg
  375.  
  376.  
  377. ;----  process_CmdLine  ---------------------------------------------------;
  378. ;  Purpose:    Processes commandline arguments.                            ;
  379. ;  Notes:      A switch character by itself is ignored.                    ;
  380. ;              No arguments whatsoever causes help flag to be set.         ;
  381. ;  Entry:      n/a                                                         ;
  382. ;  Exit:       n/a                                                         ;
  383. ;  Calls:      skip_Spaces, get_Opt, get_Arg                               ;
  384. ;  Changes:    AX, CX, SI,                                                 ;
  385. ;              DX (get_Opt),                                               ;
  386. ;              [DFlag], [TFlag],                                           ;
  387. ;              [OptCh], [NFlag] (get_Opt),                                 ;
  388. ;              [MsgLen], [MsgTxt] (get_Arg),                               ;
  389. ;              Direction flag is cleared.                                  ;
  390. ;--------------------------------------------------------------------------;
  391. PROC process_CmdLine
  392.  
  393.           cld                                ; forward, march!
  394.           ZERO      ch
  395.           mov       cl, [CmdLen]             ; length of commandline
  396.           mov       si, OFFSET CmdLine       ; offset to start of commandline
  397.  
  398.           call      skip_Spaces              ; check if any args supplied
  399.           or        cl, cl
  400.           jnz       SHORT @@ArgLoop          ;   yep
  401.           mov       [DFlag], 1               ;   nope, so display date ...
  402.           mov       [TFlag], 1               ;     and time
  403.           jmp       SHORT @@Fin
  404.  
  405. ;
  406. ; For each blank-delineated argument on the commandline...
  407. ;
  408. @@ArgLoop:
  409.           lodsb                              ; next character
  410.           dec       cl
  411.           cmp       al, [SwitCh]             ; is it the switch character?
  412.           jnz       SHORT @@NonOpt           ;   no
  413.  
  414. ;
  415. ; Isolate each option and process it. Stop when a space is reached.
  416. ;
  417. @@OptLoop:
  418.           jcxz      SHORT @@Fin              ; abort if nothing left
  419.           lodsb
  420.           dec       cl
  421.           cmp       al, ' '
  422.           jz        SHORT @@NextArg          ; abort when space reached
  423.           call      get_Opt
  424.           jmp       @@OptLoop
  425.  
  426. ;
  427. ; Process the current argument, which is *not* an option.
  428. ; Then, *drop thru* to advance to next argument.
  429. ;
  430. @@NonOpt:
  431.           dec       si                       ; back up one character
  432.           inc       cl
  433.           call      get_Arg
  434.  
  435. ;
  436. ; Skip over spaces until next argument is reached.
  437. ;
  438. @@NextArg:
  439.           call      skip_Spaces
  440.           or        cl, cl
  441.           jnz       @@ArgLoop
  442.  
  443. @@Fin:
  444.           ret
  445. ENDP process_CmdLine
  446.  
  447.  
  448. ;--------------------------------------------------------------------------;
  449. ;                         E N T R Y   P O I N T                            ;
  450. ;--------------------------------------------------------------------------;
  451. ;----  main  --------------------------------------------------------------;
  452. ;  Purpose:    Main section of program.                                    ;
  453. ;  Notes:      none                                                        ;
  454. ;  Entry:      Arguments as desired                                        ;
  455. ;  Exit:       Return code as follows:                                     ;
  456. ;                   0 => program ran successfully                          ;
  457. ;                   1 => on-line help requested                            ;
  458. ;  Calls:      process_CmdLine, fputs, putchar, getdate, put_TwoDigits,    ;
  459. ;                   gettime                                                ;
  460. ;  Changes:    n/a                                                         ;
  461. ;--------------------------------------------------------------------------;
  462. main:
  463.  
  464. ;
  465. ; Process commandline arguments. If the variable HFlag is set, then
  466. ; on-line help is displayed and the program immediately terminates.
  467. ;
  468.           call      process_CmdLine          ; process commandline args
  469.  
  470.           cmp       [HFlag], 0               ; is help needed?
  471.           jz        SHORT @@NoHelp           ;   no
  472.           mov       [RCode], ERRH            ;   yes, so set return code
  473.           mov       bx, STDERR
  474.           mov       dx, OFFSET HelpMsg       ;     point to help message
  475.           call      fputs                    ;     display it
  476.           jmp       SHORT @@Fin              ;     and jump to end of program
  477.  
  478. ;
  479. ; Display any message from commandline then get keypress from user.
  480. ;
  481. @@NoHelp:
  482.           mov       bx, STDOUT               ; everything to stdout
  483.           cmp       [MsgLen], 0              ; anything to print out?
  484.           jz        SHORT @@Date?            ;   nope
  485.           mov       dx, [MsgTxt]             ; display message text
  486.           call      fputs
  487.           mov       dl, ' '                  ; and a space
  488.           call      putchar
  489.  
  490. @@Date?:
  491.           cmp       [DFlag], 0
  492.           jz        SHORT @@Time?
  493.  
  494.           call      getdate
  495.           mov       al, dh                   ; dh = month
  496.           call      put_TwoDigits
  497.           mov       al, dl                   ; dl = day
  498.           mov       dl, DATE_SEP             ; now we can use dl for DATE_SEP
  499.           call      putchar
  500.           call      put_TwoDigits
  501.           call      putchar                  ; dl still holds DATE_SEP
  502.           mov       ax, cx                   ; cx = year
  503.           sub       ax, 1900                 ; assume 20th century
  504.           call      put_TwoDigits
  505.           mov       dl, ' '
  506.           call      putchar
  507.  
  508. @@Time?:
  509.           cmp       [TFlag], 0               ; display time?
  510.           jz        SHORT @@FinalEOL?        ;   no
  511.  
  512.           call      gettime
  513.           mov       al, ch                   ; ch = hour
  514.           call      put_TwoDigits
  515.           mov       dl, TIME_SEP
  516.           call      putchar
  517.           mov       al, cl                   ; cl = minutes
  518.           call      put_TwoDigits
  519.  
  520. @@FinalEOL?:
  521.           cmp       [NFlag], 0               ; suppress final CR/LF?
  522.           jnz       SHORT @@Fin              ;   no
  523.  
  524.           mov       dx, OFFSET EOL+1
  525.           call      fputs
  526.  
  527. ;
  528. ; Ok, let's terminate the program and exit with proper return code.
  529. ;
  530. @@Fin:
  531.           mov       al, [RCode]
  532.           mov       ah, 4ch
  533.           int       DOS
  534.  
  535. EVEN
  536. Buffer   db    ?                          ; space for single character
  537.                                           ; nb: shared by fgetc() & fputc()
  538.  
  539.  
  540. ;-------------------------------------------------------------------------;
  541. ;  Purpose:    Reads a character from specified device.
  542. ;  Notes:      No checks are done on BX's validity.
  543. ;              Buffer is shared by fputc(). Do *NOT* use in a 
  544. ;                 multitasking environment like DESQview.
  545. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  546. ;  Entry:      BX = device handle.
  547. ;  Exit:       AL = character,
  548. ;              Carry flag set on error (AX holds error code).
  549. ;  Calls:      none
  550. ;  Changes:    AX
  551. ;              flags
  552. ;-------------------------------------------------------------------------;
  553. PROC fgetc
  554.  
  555.    push     cx dx
  556. IF @DataSize NE 0
  557.    push     ds
  558.    mov      ax, @data
  559.    mov      ds, ax
  560. ENDIF
  561.  
  562.    mov      dx, OFFSET Buffer             ; point to storage
  563.    mov      cx, 1                         ; only need 1 char
  564.    mov      ah, 3fh
  565.    int      DOS                           ; get it
  566.    jc       SHORT @@Fin                   ; abort on error
  567.    mov      al, [Buffer]
  568.  
  569. @@Fin:
  570. IF @DataSize NE 0
  571.    pop      ds
  572. ENDIF
  573.    pop      dx cx
  574.    ret
  575.  
  576. ENDP fgetc
  577.  
  578.  
  579. ;-------------------------------------------------------------------------;
  580. ;  Purpose:    Writes a character to specified device.
  581. ;  Notes:      No checks are done on BX's validity.
  582. ;              Buffer is shared by fputc(). Do *NOT* use in a 
  583. ;                 multitasking environment like DESQview.
  584. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  585. ;  Entry:      AL = character to display,
  586. ;              BX = device handle.
  587. ;  Exit:       AL = 1 if successful,
  588. ;              Carry flag set on error (AX holds error code).
  589. ;  Calls:      none
  590. ;  Changes:    AX
  591. ;-------------------------------------------------------------------------;
  592. PROC fputc
  593.  
  594.    push     cx dx
  595. IF @DataSize NE 0
  596.    push     ds
  597.    mov      dx, @data
  598.    mov      ds, ax
  599. ENDIF
  600.  
  601.    mov      dx, OFFSET Buffer             ; point to storage
  602.    mov      [Buffer], al                  ; save char
  603.    mov      cx, 1                         ; only write 1 char
  604.    mov      ah, 40h
  605.    int      DOS
  606.  
  607. IF @DataSize NE 0
  608.    pop      ds
  609. ENDIF
  610.    pop      dx cx
  611.    ret
  612.  
  613. ENDP fputc
  614.  
  615.  
  616. ;-------------------------------------------------------------------------;
  617. ;  Purpose:    Reads a character from STDIN.
  618. ;  Notes:      Character is echoed to display.
  619. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  620. ;  Entry:      n/a
  621. ;  Exit:       AL = character.
  622. ;  Calls:      none
  623. ;  Changes:    AX
  624. ;-------------------------------------------------------------------------;
  625. PROC getchar
  626.  
  627.    mov      ah, 1
  628.    int      DOS
  629.    ret
  630.  
  631. ENDP getchar
  632.  
  633.  
  634. ;-------------------------------------------------------------------------;
  635. ;  Purpose:    Writes a character to STDOUT device.
  636. ;  Notes:      none
  637. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  638. ;  Entry:      DL = character to display.
  639. ;  Exit:       n/a
  640. ;  Calls:      none
  641. ;  Changes:    none
  642. ;-------------------------------------------------------------------------;
  643. PROC putchar
  644.  
  645.    push     ax
  646.    mov      ah, 2
  647.    int      DOS
  648.    pop      ax
  649.    ret
  650.  
  651. ENDP putchar
  652.  
  653.  
  654. ;-------------------------------------------------------------------------;
  655. ;  Purpose:    Checks if a character is ready for input from STDIN.
  656. ;  Notes:      none
  657. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  658. ;  Entry:      n/a
  659. ;  Exit:       zf = 1 if character available.
  660. ;  Calls:      none
  661. ;  Changes:    flags
  662. ;-------------------------------------------------------------------------;
  663. PROC kbhit
  664.  
  665.    push     ax
  666.    mov      ah, 0bh
  667.    int      DOS
  668.    cmp      al, 0ffh                      ; AL = FFh if character ready
  669.    pop      ax
  670.    ret
  671.  
  672. ENDP kbhit
  673.  
  674.  
  675. EVEN
  676. ;-------------------------------------------------------------------------;
  677. ;  Purpose:    Writes an ASCIIZ string to specified device.
  678. ;  Notes:      A zero-length string doesn't seem to cause problems when
  679. ;                 this output function is used.
  680. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  681. ;  Entry:      BX = device handle,
  682. ;              DS:DX = pointer to string.
  683. ;  Exit:       Carry flag set if EOS wasn't found or handle is invalid.
  684. ;  Calls:      strlen
  685. ;  Changes:    none
  686. ;-------------------------------------------------------------------------;
  687. PROC fputs
  688.  
  689.    push     ax cx di es
  690.    mov      ax, ds
  691.    mov      es, ax
  692.    mov      di, dx
  693.    call     strlen                        ; set CX = length of string
  694.    jc       SHORT @@Fin                   ; abort if problem finding end
  695.    mov      ah, 40h                       ; MS-DOS raw output function
  696.    int      DOS
  697. @@Fin:
  698.    pop      es di cx ax
  699.    ret
  700.  
  701. ENDP fputs
  702.  
  703.  
  704. EVEN
  705. ;-------------------------------------------------------------------------;
  706. ;  Purpose:    Writes an error message to stderr.
  707. ;  Notes:      none
  708. ;  Requires:   8086-class CPU and DOS v2.0 or better.
  709. ;  Entry:      DS:DX = pointer to error message.
  710. ;  Exit:       n/a
  711. ;  Calls:      fputs
  712. ;  Changes:    none
  713. ;-------------------------------------------------------------------------;
  714. PROC errmsg
  715.  
  716.    push     bx dx
  717.    mov      bx, STDERR
  718.    mov      dx, OFFSET ProgName           ; display program name
  719.    call     fputs
  720.    pop      dx                            ; recover calling parameters
  721.    push     dx                            ; and save again to avoid change
  722.    call     fputs                         ; display error message
  723.    mov      dx, OFFSET EOL
  724.    call     fputs
  725.    pop      dx bx
  726.    ret
  727.  
  728. ENDP errmsg
  729.  
  730.  
  731. EVEN
  732. ;-------------------------------------------------------------------------;
  733. ;  Purpose:    Gets current system date, based on DOS's internal clock.
  734. ;  Notes:      none
  735. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  736. ;  Entry:      n/a
  737. ;  Exit:       AL = day of week (0 = Sunday)
  738. ;              DL = day (1 to 31)
  739. ;              DH = month (1 to 12)
  740. ;              CX = year (1980 to 2099)
  741. ;  Calls:      none
  742. ;  Changes:    AX, CX, DX
  743. ;-------------------------------------------------------------------------;
  744. PROC getdate
  745.  
  746.    mov      ah, 2ah                       ; MS-DOS get system date function
  747.    int      DOS
  748.    ret
  749.  
  750. ENDP getdate
  751.  
  752.  
  753. ;-------------------------------------------------------------------------;
  754. ;  Purpose:    Gets current system time, based on DOS's internal clock.
  755. ;  Notes:      none
  756. ;  Requires:   8086-class CPU and DOS v1.0 or better.
  757. ;  Entry:      n/a
  758. ;  Exit:       CL = minutes (0 - 59)
  759. ;              CH = hour (0 - 23)
  760. ;              DL = hundredths of seconds (0 - 99)
  761. ;              DH = seconds (0 - 59)
  762. ;  Calls:      none
  763. ;  Changes:    CX, DX
  764. ;-------------------------------------------------------------------------;
  765. PROC gettime
  766.  
  767.    push     ax
  768.    mov      ah, 2ch                       ; MS-DOS get system time function
  769.    int      DOS
  770.    pop      ax
  771.    ret
  772.  
  773. ENDP gettime
  774.  
  775.  
  776. EVEN
  777. ;-------------------------------------------------------------------------;
  778. ;  Purpose:    Converts an *unsigned* integer in range [0, 65535] to
  779. ;              an ASCIIZ string of digits.
  780. ;  Notes:      No checks are made to ensure storage area is big enough.
  781. ;              A terminating null is added.
  782. ;  Requires:   8086-class CPU.
  783. ;  Entry:      AX = unsigned integer value,
  784. ;              ES:DI = pointer to string storage area.
  785. ;  Exit:       ES:DI = pointer to start of string.
  786. ;  Calls:      none
  787. ;  Changes:    DI
  788. ;-------------------------------------------------------------------------;
  789. PROC utoa
  790.  
  791.    push     ax bx cx dx di
  792.    mov      bx, 10                        ; conversion factor
  793.    ZERO     cx                            ; track # digits in string
  794.  
  795. @@NewDigit:                               ; for each character
  796.    ZERO     dx                            ; dx:ax is dividend so make dx 0
  797.    div      bx                            ; ax = dx:ax / 10
  798.    push     dx                            ; dx = dx:ax mod 10
  799.    inc      cl                            ; one more digit processed
  800.    or       ax, ax                        ; anything left?
  801.    jnz      @@NewDigit
  802.  
  803. @@NextChar:                               ; for each power of ten
  804.    pop      ax
  805.    add      al, '0'
  806.    mov      [BYTE PTR di], al
  807.    inc      di
  808.    loop     @@NextChar
  809.    mov      [BYTE PTR di], EOS            ; don't forget to end it!
  810.  
  811.    pop      di dx cx bx ax
  812.    ret
  813.  
  814. ENDP utoa
  815.  
  816.  
  817. EVEN
  818. ;-------------------------------------------------------------------------;
  819. ;  Purpose:    Converts character to lowercase.
  820. ;  Notes:      none
  821. ;  Requires:   8086-class CPU.
  822. ;  Entry:      AL = character to be converted.
  823. ;  Exit:       AL = converted character.
  824. ;  Calls:      none
  825. ;  Changes:    AL
  826. ;              flags
  827. ;-------------------------------------------------------------------------;
  828. PROC tolower
  829.  
  830.    cmp      al, 'A'                       ; if < 'A' then done
  831.    jb       SHORT @@Fin
  832.    cmp      al, 'Z'                       ; if > 'Z' then done
  833.    ja       SHORT @@Fin
  834.    or       al, 20h                       ; make it lowercase
  835. @@Fin:
  836.    ret
  837.  
  838. ENDP tolower
  839.  
  840.  
  841. ;-------------------------------------------------------------------------;
  842. ;  Purpose:    Converts character to uppercase.
  843. ;  Notes:      none
  844. ;  Requires:   8086-class CPU.
  845. ;  Entry:      AL = character to be converted.
  846. ;  Exit:       AL = converted character.
  847. ;  Calls:      none
  848. ;  Changes:    AL
  849. ;              flags
  850. ;-------------------------------------------------------------------------;
  851. PROC toupper
  852.  
  853.    cmp      al, 'a'                       ; if < 'a' then done
  854.    jb       SHORT @@Fin
  855.    cmp      al, 'z'                       ; if > 'z' then done
  856.    ja       SHORT @@Fin
  857.    and      al, not 20h                   ; make it lowercase
  858. @@Fin:
  859.    ret
  860.  
  861. ENDP toupper
  862.  
  863.  
  864. EVEN
  865. ;-------------------------------------------------------------------------;
  866. ;  Purpose:    Calculates length of an ASCIIZ string.
  867. ;  Notes:      Terminal char is _not_ included in the count.
  868. ;  Requires:   8086-class CPU.
  869. ;  Entry:      ES:DI = pointer to string.
  870. ;  Exit:       CX = length of string,
  871. ;              cf = 0 and zf = 1 if EOS found,
  872. ;              cf = 1 and zf = 0 if EOS not found within segment.
  873. ;  Calls:      none
  874. ;  Changes:    CX,
  875. ;              flags
  876. ;-------------------------------------------------------------------------;
  877. PROC strlen
  878.  
  879.    push     ax di
  880.    pushf
  881.    cld                                    ; scan forward only
  882.    mov      al, EOS                       ; character to search for
  883.    mov      cx, di                        ; where are we now
  884.    not      cx                            ; what's left in segment - 1
  885.    push     cx                            ; save char count
  886.    repne    scasb
  887.    je       SHORT @@Done
  888.    scasb                                  ; test final char
  889.    dec      cx                            ; avoids trouble with "not" below
  890.  
  891. @@Done:
  892.    pop      ax                            ; get original count
  893.    sub      cx, ax                        ; subtract current count
  894.    not      cx                            ; and invert it
  895.    popf                                   ; restore df
  896.    dec      di
  897.    cmp      [BYTE PTR es:di], EOS
  898.    je       SHORT @@Fin                   ; cf = 0 if equal
  899.    stc                                    ; set cf => error
  900.  
  901. @@Fin:
  902.    pop      di ax
  903.    ret
  904.  
  905. ENDP strlen
  906.  
  907.  
  908. END
  909.