home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------------;
- ; Program: Ring .Asm ;
- ; Purpose: Rings the console bell. ;
- ; Notes: Compiles under TURBO Assembler, v2.0. Should work on any ;
- ; machine running MS-DOS, v2.xx or higher. ;
- ; Status: Released into the public domain. Enjoy! If you use it, ;
- ; let me know what you think. You don't have to send ;
- ; any money, just comments and suggestions. ;
- ; Updates: 23-Apr-89, v1.0, GAT ;
- ; - initial version. ;
- ; 22-Apr-90, v1.1, GAT ;
- ; - revised all procedures based on work on ASK. ;
- ; 05-May-90, GAT ;
- ; - fixed bug in handling of non-zero return codes. ;
- ; 13-May-90, v1.2, GAT ;
- ; - added '-e' option to test for nonzero errorlevels. ;
- ; 08-Jul-90, GAT ;
- ; - added macros to push/pop registers. ;
- ; 28-Aug-90, v1.3a, GAT ;
- ; - put equates and macros in separate files. ;
- ; - put common routines in libs. ;
- ; 28-Dec-90, v1.4a, GAT ;
- ; - added support under DOS v4.0 for '-e' option. ;
- ; 15-Oct-91, v1.4b, GAT ;
- ; - revised include file names. ;
- ; - added support for DOS v5.0. ;
- ;--------------------------------------------------------------------------;
-
- ;--------------------------------------------------------------------------;
- ; Author: George A. Theall ;
- ; Phone: +1 215 662 0558 ;
- ; SnailMail: TifaWARE ;
- ; 506 South 41st St., #3M ;
- ; Philadelphia, PA. 19104 USA ;
- ; E-Mail: theall@gdalsrv.sas.upenn.edu (Internet) ;
- ;--------------------------------------------------------------------------;
-
- %NEWPAGE
- ;--------------------------------------------------------------------------;
- ; D I R E C T I V E S ;
- ;--------------------------------------------------------------------------;
- DOSSEG
- MODEL tiny
-
- IDEAL
- LOCALS
- JUMPS
-
- ;
- ; This section comes from Misc.Inc.
- ;
- @16BIT EQU (@CPU AND 8) EQ 0
- @32BIT EQU (@CPU AND 8)
- MACRO ZERO RegList ;; Zeros registers
- IRP Reg, <RegList>
- xor Reg, Reg
- ENDM
- ENDM
-
- ;
- ; This section comes from DOS.Inc.
- ;
- BELL EQU 7
- BS EQU 8
- TAB EQU 9
- CR EQU 13
- LF EQU 10
- ESCAPE EQU 27 ; nb: ESC is a TASM keyword
- SPACE EQU ' '
- KEY_F1 EQU 3bh
- KEY_F2 EQU 3ch
- KEY_F3 EQU 3dh
- KEY_F4 EQU 3eh
- KEY_F5 EQU 3fh
- KEY_F6 EQU 40h
- KEY_F7 EQU 41h
- KEY_F8 EQU 42h
- KEY_F9 EQU 43h
- KEY_F10 EQU 44h
- KEY_HOME EQU 47h
- KEY_UP EQU 48h
- KEY_PGUP EQU 49h
- KEY_LEFT EQU 4bh
- KEY_RIGHT EQU 4dh
- KEY_END EQU 4fh
- KEY_DOWN EQU 50h
- KEY_PGDN EQU 51h
- KEY_INS EQU 52h
- KEY_DEL EQU 53h
- KEY_C_F1 EQU 5eh
- KEY_C_F2 EQU 5fh
- KEY_C_F3 EQU 60h
- KEY_C_F4 EQU 61h
- KEY_C_F5 EQU 62h
- KEY_C_F6 EQU 63h
- KEY_C_F7 EQU 64h
- KEY_C_F8 EQU 65h
- KEY_C_F9 EQU 66h
- KEY_C_F10 EQU 67h
- KEY_C_LEFT EQU 73h
- KEY_C_RIGHT EQU 74h
- KEY_C_END EQU 75h
- KEY_C_PGDN EQU 76h
- KEY_C_HOME EQU 77h
- KEY_C_PGUP EQU 84h
- KEY_F11 EQU 85h
- KEY_F12 EQU 86h
- KEY_C_F11 EQU 89h
- KEY_C_F12 EQU 8ah
- DOS EQU 21h ; main MSDOS interrupt
- STDIN EQU 0 ; standard input
- STDOUT EQU 1 ; standard output
- STDERR EQU 2 ; error output
- STDAUX EQU 3 ; COM port
- STDPRN EQU 4 ; printer
- STRUC HOOK
- Vector DB ? ; vector hooked into
- OldISR DD ? ; entry point to old ISR
- NewISR DD ? ; entry point to new ISR
- ENDS
- GLOBAL at : PROC
- GLOBAL errmsg : PROC
- GLOBAL ProgName : BYTE ; needed for errmsg()
- GLOBAL EOL : BYTE ; ditto
- GLOBAL fgetc : PROC
- GLOBAL fputc : PROC
- GLOBAL fputs : PROC
- GLOBAL getchar : PROC
- GLOBAL getdate : PROC
- GLOBAL getswtch : PROC
- GLOBAL gettime : PROC
- GLOBAL getvdos : PROC
- GLOBAL getvect : PROC
- GLOBAL isatty : PROC
- GLOBAL kbhit : PROC
- GLOBAL pause : PROC
- GLOBAL putchar : PROC
- GLOBAL setvect : PROC
- GLOBAL sleep : PROC
- GLOBAL fake_Env : PROC
- GLOBAL install_TSR : PROC
- GLOBAL uninstall_TSR : PROC
-
- ;
- ; This section comes from Math.Inc.
- ;
- GLOBAL atoi : PROC
- GLOBAL atou : PROC
- GLOBAL utoa : PROC
-
- ;
- ; This section comes from String.Inc.
- ;
- EOS EQU 0 ; terminates strings
- GLOBAL isdigit : PROC
- GLOBAL islower : PROC
- GLOBAL isupper : PROC
- GLOBAL iswhite : PROC
- GLOBAL strchr : PROC
- GLOBAL strcmp : PROC
- GLOBAL strlen : PROC
- GLOBAL tolower : PROC
- GLOBAL toupper : PROC
-
-
- VERSION equ '1.4b' ; current version of program
- ERRH equ 1 ; errorlevel if help given
- COUNT_UPP_LIMIT equ 15 ; upper limit for rep count
- ; NB: This limit has also
- ; been coded in HelpMsg
-
-
- %NEWPAGE
- ;--------------------------------------------------------------------------;
- ; C O D E S E G M E N T ;
- ;--------------------------------------------------------------------------;
- CODESEG
-
- ORG 80h ; commandline
- LABEL CmdLen BYTE
- db ?
- LABEL CmdLine BYTE
- db 127 dup (?)
-
- ORG 100h ; start of .COM file
- STARTUPCODE
- jmp main ; skip over data and stack
-
- %NEWPAGE
- ;--------------------------------------------------------------------------;
- ; D A T A ;
- ;--------------------------------------------------------------------------;
- LABEL ProgName BYTE
- db 'ring: ', EOS
- LABEL EOL BYTE
- db '.', CR, LF, EOS
- LABEL HelpMsg BYTE
- db CR, LF
- DB 'TifaWARE RING, v', VERSION, ', ', ??Date
- db ' - rings the console bell.', CR, LF
- db 'Usage: ring [-options] [count]', CR, LF, LF
- db 'Options:', CR, LF
- db ' -e = ring bell only if errorlevel is non-zero', CR, LF
- db ' -? = display this help message', CR, LF, LF
- db 'count denotes a repetition count and must be between'
- db ' 0 and 15.', CR, LF
- db 'The default value of count is 3.', CR, LF, EOS
-
- LABEL Err1Msg BYTE
- db 'illegal option -- '
- LABEL OptCh BYTE
- db ?
- db EOS
- LABEL Err2Msg BYTE
- db 'invalid repetition count -- ', EOS
- LABEL Err3Msg BYTE
- db 'unable to locate errorlevel', EOS
-
- STRUC ERRLOC ; structure holding addresses
- vDos DW ? ; minor SHL 8 + major
- Loc DW ? ; offset within segment
- ENDS
- ErrLocTbl ERRLOC <30 SHL 8 + 3, 0beaH> ; for DOS v3.30
- ERRLOC <00 SHL 8 + 4, 0f2bH> ; for DOS v4.0
- ERRLOC <00 SHL 8 + 5, 02a3H> ; for DOS v5.0
- ERRLOC <0, 0> ; >>>must be last<<<
-
- SwitCh db '-' ; char introducing options
- EFlag db 0 ; flag for testing errorlevel
- HFlag db 0 ; flag for on-line help
- Count db 3 ; default number of rings
- RCode db 0 ; program return code
-
-
- %NEWPAGE
- ;--------------------------------------------------------------------------;
- ; P R O C E D U R E S ;
- ;--------------------------------------------------------------------------;
- ;---- get_ErrLvl --------------------------------------------------------;
- ; Purpose: Gets errorlevel from previously executed program. ;
- ; Notes: Thanks to Josep Fortiana Gregori (D3ESJFG0@EB0UB011) for ;
- ; providing a code sample from which this proc was ;
- ; derived and to Yan Juras for suggesting at which ;
- ; offset to look for this value. ;
- ; Requires: 8086-class CPU and DOS v3.30 or v4.0 (as sold in USA). ;
- ; Entry: DS = PSP address of program (OK if not changed since ;
- ; program started. ;
- ; Exit: AL = errorlevel, ;
- ; cf = 1 if DOS version is unsupported or DOS not found. ;
- ; Calls: getvdos ;
- ; Changes: AX, ;
- ; flags ;
- ;--------------------------------------------------------------------------;
- PROC get_ErrLvl
-
- push bp dx es
-
- ; Make sure a supported version of DOS is being used.
- call getvdos ; AL = major version
- mov bp, OFFSET ErrLocTbl
-
- @@NextVer:
- cmp [(ERRLOC PTR bp).vDOS], ax ; supported version?
- je SHORT @@FindPSP ; yes
- add bp, SIZE ErrLocTbl ; no
- cmp [(ERRLOC PTR bp).vDOS], 0 ; at end of table?
- je SHORT @@NoCanDo ; yes
- jmp SHORT @@NextVer ; no
-
- ; Find the PSP for the version of COMMAND.COM which called us.
- ; This approach relies on the observation that COMMAND.COM
- ; assigns its own PSP as the calling PSP at offset 16h.
- ;
- ;
- ; NB: Abort if calling PSP is above current PSP. This happens
- ; when running under an alternate shell like MKS Toolkit.
- @@FindPSP:
- mov ax, ds
-
- @@LoopBack:
- mov es, ax
- mov dx, [es:16h] ; get caller's PSP (undocumented)
- xchg ax, dx
- cmp ax, dx
- jb @@LoopBack
- ja SHORT @@NoCanDo ; avoid infinite loop if no DOS
-
- clc ; signal no error
- mov bp, [(ERRLOC PTR bp).Loc]
- mov al, [es:bp]
- jmp SHORT @@Fin
-
- @@NoCanDo:
- stc ; signal an error
-
- @@Fin:
- pop es dx bp
- ret
- ENDP get_ErrLvl
-
-
- ;---- skip_Spaces -------------------------------------------------------;
- ; Purpose: Skips past spaces in a string. ;
- ; Notes: Scanning stops with either a non-space *OR* CX = 0. ;
- ; Entry: DS:SI = start of string to scan. ;
- ; Exit: AL = next non-space character, ;
- ; CX is adjusted as necessary, ;
- ; DS:SI = pointer to next non-space. ;
- ; Calls: none ;
- ; Changes: AL, CX, SI ;
- ;--------------------------------------------------------------------------;
- PROC skip_Spaces
-
- jcxz SHORT @@Fin
- @@NextCh:
- lodsb
- cmp al, ' '
- loopz @@NextCh
- jz SHORT @@Fin ; CX = 0; don't adjust
-
- inc cx ; adjust counters if cx > 0
- dec si
-
- @@Fin:
- ret
- ENDP skip_Spaces
-
-
- ;---- get_Opt -----------------------------------------------------------;
- ; Purpose: Get a commandline option. ;
- ; Notes: none ;
- ; Entry: AL = option character. ;
- ; Exit: n/a ;
- ; Calls: tolower, errmsg, get_ErrLvl ;
- ; Changes: AX, DX, ;
- ; [OptCh], [HFlag], [EFlag], [RCode] ;
- ;--------------------------------------------------------------------------;
- PROC get_Opt
-
- mov [OptCh], al ; save for later
- call tolower ; use only lowercase in cmp.
- cmp al, 'e'
- jz SHORT @@OptE
- cmp al, '?'
- jz SHORT @@OptH
- mov dx, OFFSET Err1Msg ; unrecognized option
- call errmsg ; then *** DROP THRU *** to OptH
-
- ; Various possible options.
- @@OptH:
- mov [HFlag], 1 ; set help flag
- jmp SHORT @@Fin
-
- @@OptE:
- mov [EFlag], 1 ; conditionally ring bell
- call get_ErrLvl ; get earlier errorlevel
- jnc SHORT @@SaveErrLvl ; continue; no problems
- mov dx, OFFSET Err3Msg ; can't find errorlevel
- call errmsg
- jmp @@OptH
-
- @@SaveErrLvl:
- mov [RCode], al ; use it as our return code
-
- @@Fin:
- ret
- ENDP get_Opt
-
-
- ;---- get_Arg -----------------------------------------------------------;
- ; Purpose: Gets a non-option from the set of commandline arguments. ;
- ; Notes: Anything left on the commandline is user's message text. ;
- ; Entry: CX = count of characters left in commandline, ;
- ; DS:SI = pointer to argument to process. ;
- ; Exit: CX = count of characters left _after_ processing, ;
- ; DS:SI = pointer to whitespace _after_ argument. ;
- ; Calls: isdigit, fputs, atou ;
- ; Changes: CX, DX, SI ;
- ; [HFlag], [Count] ;
- ;--------------------------------------------------------------------------;
- PROC get_Arg
-
- call isdigit ; if not a digit, trouble!
- jz SHORT @@GetCount
-
- mov dx, si ; flag arg as bad
- xchg di, si
- mov al, ' '
- repne scasb ; find end of argument
- xchg di, si
- jne SHORT @@BadCount
- dec si ; overshot so back up 1 char
- inc cx
- jmp SHORT @@BadCount ; tell user it's bad
-
- @@GetCount:
- mov dx, si ; save to adjust CX and if error
- call atou
- pushf ; preserve flags
- add cx, dx ; adjust counter
- sub cx, si
- popf ; restore flags
- jc SHORT @@BadCount ; error in conversion?
- cmp ax, COUNT_UPP_LIMIT ; too big?
- ja SHORT @@BadCount ; yes
- mov [Count], al
- jmp SHORT @@Fin
-
- @@BadCount:
- push dx
- mov bl, STDERR
- mov dx, OFFSET ProgName
- call fputs
- mov dx, OFFSET Err2Msg
- call fputs
- pop dx
- mov al, [si] ; save next non-digit
- mov [BYTE PTR si], EOS ; replace with EOS
- call fputs
- mov [si], al ; restore it
- mov dx, OFFSET EOL
- call fputs
- mov [HFlag], 1
- jmp SHORT @@Fin
-
- @@Fin:
- ret
- ENDP get_Arg
-
-
- ;---- process_CmdLine ---------------------------------------------------;
- ; Purpose: Processes commandline arguments. ;
- ; Notes: A switch character by itself is ignored. ;
- ; No arguments whatsoever causes help flag to be set. ;
- ; Entry: n/a ;
- ; Exit: n/a ;
- ; Calls: skip_Spaces, get_Opt, get_Arg ;
- ; Changes: AX, CX, SI, ;
- ; DX (get_Arg), ;
- ; [OptCh], [HFlag], [EFlag] (get_Opt), ;
- ; [Count], (get_Arg), ;
- ; Direction flag is cleared. ;
- ;--------------------------------------------------------------------------;
- PROC process_CmdLine
-
- cld ; forward, march!
- ZERO ch
- mov cl, [CmdLen] ; length of commandline
- mov si, OFFSET CmdLine ; offset to start of commandline
-
- call skip_Spaces ; check if any args supplied
- or cl, cl
- jnz SHORT @@ArgLoop
- jmp SHORT @@Fin
-
- ; For each blank-delineated argument on the commandline...
- @@ArgLoop:
- lodsb ; next character
- dec cl
- cmp al, [SwitCh] ; is it the switch character?
- jnz SHORT @@NonOpt ; no
-
- ; Isolate each option and process it. Stop when a space is reached.
- @@OptLoop:
- jcxz SHORT @@Fin ; abort if nothing left
- lodsb
- dec cl
- cmp al, ' '
- jz SHORT @@NextArg ; abort when space reached
- call get_Opt
- jmp @@OptLoop
-
- ; Process the current argument, which is *not* an option.
- ; Then, *drop thru* to advance to next argument.
- @@NonOpt:
- dec si ; back up one character
- inc cl
- call get_Arg
-
- ; Skip over spaces until next argument is reached.
- @@NextArg:
- call skip_Spaces
- or cl, cl
- jnz @@ArgLoop
-
- @@Fin:
- ret
- ENDP process_CmdLine
-
-
- ;--------------------------------------------------------------------------;
- ; E N T R Y P O I N T ;
- ;--------------------------------------------------------------------------;
- ;---- main --------------------------------------------------------------;
- ; Purpose: Main section of program. ;
- ; Notes: none ;
- ; Entry: Arguments as desired ;
- ; Exit: Return code as follows: ;
- ; 0 => program ran successfully ;
- ; 1 => on-line help requested ;
- ; or whatever previous errorlevel was if '-e' option used. ;
- ; Calls: process_CmdLine, fputs, putchar ;
- ; Changes: n/a ;
- ;--------------------------------------------------------------------------;
- main:
-
- ; Process commandline arguments. If the variable HFlag is set, then
- ; on-line help is displayed and the program immediately terminates.
- call process_CmdLine ; process commandline args
-
- cmp [HFlag], 0 ; is help needed?
- jz SHORT @@NoHelp ; no
- mov [RCode], ERRH ; yes, so set return code
- mov bx, STDERR
- mov dx, OFFSET HelpMsg ; point to help message
- call fputs ; display it
- jmp SHORT @@Fin ; and jump to end of program
-
- ; Figure out whether to ring bell conditionally.
- @@NoHelp:
- cmp [EFlag], 0 ; is it conditional?
- jz SHORT @@RingBell ; no
- cmp [RCode], 0 ; yes, was errorlevel 0?
- jz SHORT @@Fin ; yes, no bell
-
- ; Determine how many times to ring the bell and do it.
- @@RingBell:
- mov cl, [Count] ; get the count
- ZERO ch ; zero out high byte of word
- jcxz SHORT @@Fin
- mov dl, BELL
- @@RingLoop:
- call putchar
- loop @@RingLoop ; repeat as necessary
-
- ; Ok, let's terminate the program and exit with proper return code.
- @@Fin:
- mov al, [RCode]
- mov ah, 4ch
- int DOS
-
- EVEN
- Buffer db ? ; space for single character
- ; nb: shared by fgetc() & fputc()
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Reads a character from specified device.
- ; Notes: No checks are done on BX's validity.
- ; Buffer is shared by fputc(). Do *NOT* use in a
- ; multitasking environment like DESQview.
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: BX = device handle.
- ; Exit: AL = character,
- ; Carry flag set on error (AX holds error code).
- ; Calls: none
- ; Changes: AX
- ; flags
- ;-------------------------------------------------------------------------;
- PROC fgetc
-
- push cx dx
- IF @DataSize NE 0
- push ds
- mov ax, @data
- mov ds, ax
- ENDIF
-
- mov dx, OFFSET Buffer ; point to storage
- mov cx, 1 ; only need 1 char
- mov ah, 3fh
- int DOS ; get it
- jc SHORT @@Fin ; abort on error
- mov al, [Buffer]
-
- @@Fin:
- IF @DataSize NE 0
- pop ds
- ENDIF
- pop dx cx
- ret
-
- ENDP fgetc
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Writes a character to specified device.
- ; Notes: No checks are done on BX's validity.
- ; Buffer is shared by fputc(). Do *NOT* use in a
- ; multitasking environment like DESQview.
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: AL = character to display,
- ; BX = device handle.
- ; Exit: AL = 1 if successful,
- ; Carry flag set on error (AX holds error code).
- ; Calls: none
- ; Changes: AX
- ;-------------------------------------------------------------------------;
- PROC fputc
-
- push cx dx
- IF @DataSize NE 0
- push ds
- mov dx, @data
- mov ds, ax
- ENDIF
-
- mov dx, OFFSET Buffer ; point to storage
- mov [Buffer], al ; save char
- mov cx, 1 ; only write 1 char
- mov ah, 40h
- int DOS
-
- IF @DataSize NE 0
- pop ds
- ENDIF
- pop dx cx
- ret
-
- ENDP fputc
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Reads a character from STDIN.
- ; Notes: Character is echoed to display.
- ; Requires: 8086-class CPU and DOS v1.0 or better.
- ; Entry: n/a
- ; Exit: AL = character.
- ; Calls: none
- ; Changes: AX
- ;-------------------------------------------------------------------------;
- PROC getchar
-
- mov ah, 1
- int DOS
- ret
-
- ENDP getchar
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Writes a character to STDOUT device.
- ; Notes: none
- ; Requires: 8086-class CPU and DOS v1.0 or better.
- ; Entry: DL = character to display.
- ; Exit: n/a
- ; Calls: none
- ; Changes: none
- ;-------------------------------------------------------------------------;
- PROC putchar
-
- push ax
- mov ah, 2
- int DOS
- pop ax
- ret
-
- ENDP putchar
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Checks if a character is ready for input from STDIN.
- ; Notes: none
- ; Requires: 8086-class CPU and DOS v1.0 or better.
- ; Entry: n/a
- ; Exit: zf = 1 if character available.
- ; Calls: none
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC kbhit
-
- push ax
- mov ah, 0bh
- int DOS
- cmp al, 0ffh ; AL = FFh if character ready
- pop ax
- ret
-
- ENDP kbhit
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Writes an ASCIIZ string to specified device.
- ; Notes: A zero-length string doesn't seem to cause problems when
- ; this output function is used.
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: BX = device handle,
- ; DS:DX = pointer to string.
- ; Exit: Carry flag set if EOS wasn't found or handle is invalid.
- ; Calls: strlen
- ; Changes: none
- ;-------------------------------------------------------------------------;
- PROC fputs
-
- push ax cx di
- IF @DataSize NE 0
- push es
- mov ax, ds
- mov es, ax
- ENDIF
- mov di, dx
- call strlen ; set CX = length of string
- jc SHORT @@Fin ; abort if problem finding end
- mov ah, 40h ; MS-DOS raw output function
- int DOS
- @@Fin:
- IF @DataSize NE 0
- pop es
- ENDIF
- pop di cx ax
- ret
-
- ENDP fputs
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Writes an error message to stderr.
- ; Notes: none
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: DS:DX = pointer to error message.
- ; Exit: n/a
- ; Calls: fputs
- ; Changes: none
- ;-------------------------------------------------------------------------;
- PROC errmsg
-
- push bx dx
- mov bx, STDERR
- mov dx, OFFSET ProgName ; display program name
- call fputs
- pop dx ; recover calling parameters
- push dx ; and save again to avoid change
- call fputs ; display error message
- mov dx, OFFSET EOL
- call fputs
- pop dx bx
- ret
-
- ENDP errmsg
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Gets version of DOS currently running.
- ; Notes: none
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: n/a
- ; Exit: AL = major version number,
- ; AH = minor version number (2.1 = 10).
- ; Calls: none
- ; Changes: AX
- ;-------------------------------------------------------------------------;
- PROC getvdos
-
- push bx cx ; DOS destroys bx and cx!
- mov ah, 30h
- int DOS
- pop cx bx
- ret
-
- ENDP getvdos
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Converts string of digits to an *unsigned* integer in
- ; range [0, 65535].
- ; Notes: Conversion stops with first non-numeric character.
- ; Requires: 8086-class CPU.
- ; Entry: DS:SI = pointer to string of digits.
- ; Exit: AX = unsigned integer (garbage if cf = 1),
- ; DS:SI = pointer to first non-digit found,
- ; cf = 1 if number is too big.
- ; Calls: none
- ; Changes: AX, SI
- ; flags
- ;-------------------------------------------------------------------------;
- PROC atou
-
- push bx cx dx ; DX destroyed by MUL below
- ZERO ax ; AX = digit to convert
- ZERO bx ; BX = integer word
- mov cx, 10 ; CX = conversion factor
-
- @@NextCh:
- mov bl, [si] ; get character
- cmp bl, '0' ; test if a digit
- jb SHORT @@Fin
- cmp bl, '9'
- ja SHORT @@Fin
- inc si ; bump up pointer
- mul cx ; multiply old result by 10
- jc SHORT @@Overflow
- sub bl, '0' ; convert digit
- add ax, bx ; add current value
- jnc @@NextCh ; continue unless result too big
-
- @@Overflow:
- ZERO cx ; denotes overflow
- jmp @@NextCh
-
- @@Fin:
- cmp cx, 10 ; cf = (cx != 10)
- pop dx cx bx
- ret
-
- ENDP atou
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Tests if character is a valid ASCII digit.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be tested.
- ; Exit: Zero flag set if true, cleared otherwise.
- ; Calls: none
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC isdigit
-
- cmp al, '0' ; if < '0' zf = 0
- jb SHORT @@Fin
- cmp al, '9' ; if > '9' zf = 0
- ja SHORT @@Fin
- cmp al, al ; set Z flag
- @@Fin:
- ret
-
- ENDP isdigit
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Tests if character is lowercase.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be tested.
- ; Exit: Zero flag set if true, cleared otherwise.
- ; Calls: none
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC islower
-
- cmp al, 'a' ; if < 'a' zf = 0
- jb SHORT @@Fin
- cmp al, 'z' ; if > 'z' zf = 0
- ja SHORT @@Fin
- cmp al, al ; set Z flag
- @@Fin:
- ret
-
- ENDP islower
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Tests if character is uppercase.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be tested.
- ; Exit: Zero flag set if true, cleared otherwise.
- ; Calls: none
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC isupper
-
- cmp al, 'A' ; if < 'A' zf = 0
- jb SHORT @@Fin
- cmp al, 'Z' ; if > 'Z' zf = 0
- ja SHORT @@Fin
- cmp al, al ; set Z flag
- @@Fin:
- ret
-
- ENDP isupper
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Tests if character is an ASCII whitespace.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be tested.
- ; Exit: Zero flag set if true, cleared otherwise.
- ; Calls: none
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC iswhite
-
- cmp al, SPACE ; if == SPACE then zf = 1
- jz SHORT @@Fin
- cmp al, TAB ; if == TAB then zf = 1
- jz SHORT @@Fin
- cmp al, LF ; if == LF then zf = 1
- jz SHORT @@Fin
- cmp al, CR ; if == CR then zf = 1
- @@Fin:
- ret
-
- ENDP iswhite
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Converts character to lowercase.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be converted.
- ; Exit: AL = converted character.
- ; Calls: none
- ; Changes: AL
- ; flags
- ;-------------------------------------------------------------------------;
- PROC tolower
-
- cmp al, 'A' ; if < 'A' then done
- jb SHORT @@Fin
- cmp al, 'Z' ; if > 'Z' then done
- ja SHORT @@Fin
- or al, 20h ; make it lowercase
- @@Fin:
- ret
-
- ENDP tolower
-
-
- ;-------------------------------------------------------------------------;
- ; Purpose: Converts character to uppercase.
- ; Notes: none
- ; Requires: 8086-class CPU.
- ; Entry: AL = character to be converted.
- ; Exit: AL = converted character.
- ; Calls: none
- ; Changes: AL
- ; flags
- ;-------------------------------------------------------------------------;
- PROC toupper
-
- cmp al, 'a' ; if < 'a' then done
- jb SHORT @@Fin
- cmp al, 'z' ; if > 'z' then done
- ja SHORT @@Fin
- and al, not 20h ; make it lowercase
- @@Fin:
- ret
-
- ENDP toupper
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Calculates length of an ASCIIZ string.
- ; Notes: Terminal char is _not_ included in the count.
- ; Requires: 8086-class CPU.
- ; Entry: ES:DI = pointer to string.
- ; Exit: CX = length of string,
- ; cf = 0 and zf = 1 if EOS found,
- ; cf = 1 and zf = 0 if EOS not found within segment.
- ; Calls: none
- ; Changes: CX,
- ; flags
- ;-------------------------------------------------------------------------;
- PROC strlen
-
- push ax di
- pushf
- cld ; scan forward only
- mov al, EOS ; character to search for
- mov cx, di ; where are we now
- not cx ; what's left in segment - 1
- push cx ; save char count
- repne scasb
- je SHORT @@Done
- scasb ; test final char
- dec cx ; avoids trouble with "not" below
-
- @@Done:
- pop ax ; get original count
- sub cx, ax ; subtract current count
- not cx ; and invert it
- popf ; restore df
- dec di
- cmp [BYTE PTR es:di], EOS
- je SHORT @@Fin ; cf = 0 if equal
- stc ; set cf => error
-
- @@Fin:
- pop di ax
- ret
-
- ENDP strlen
-
-
- END
-