home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / batch / errlvl12.zip / ERRLVL.ASM next >
Assembly Source File  |  1991-10-15  |  32KB  |  847 lines

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