home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------------;
- ; Program: Ask .Asm ;
- ; Purpose: Ask question in batch file and time out if desired. ;
- ; 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-90, v1.0, GAT ;
- ; - initial version. ;
- ; 13-May-90, GAT ;
- ; - fixed problem with return code if time-out reached. ;
- ; 08-Jul-90, GAT ;
- ; - added macros to push/pop registers. ;
- ; 28-Aug-90, v1.1a, GAT ;
- ; - put equates and macros in separate files. ;
- ; - put common routines in libs. ;
- ;--------------------------------------------------------------------------;
-
- ;--------------------------------------------------------------------------;
- ; Author: George A. Theall ;
- ; Phone: +1 215 662 0558 ;
- ; SnailMail: TifaWARE ;
- ; 506 South 41st St., #3M ;
- ; Philadelphia, PA. 19104 USA ;
- ; E-Mail: GTHEALL@PENNDRLS.UPENN.EDU (Internet) ;
- ;--------------------------------------------------------------------------;
-
- ;--------------------------------------------------------------------------;
- ; D I R E C T I V E S ;
- ;--------------------------------------------------------------------------;
- DOSSEG
- MODEL tiny
-
- IDEAL
- LOCALS
- JUMPS
-
- ;
- ; This section comes from D:\ASM\INCLUDE\Equates.Inc.
- ;
- EOS EQU 0 ; terminates strings
- 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
-
- ;
- ; This section comes from D:\ASM\INCLUDE\Macros.Inc.
- ;
- MACRO Pop_M RegList ;; Pops registers off stack.
- IRP Reg, <RegList>
- IFIDNI <Reg>, <flags>
- popf
- ELSE
- pop Reg
- ENDIF
- ENDM
- ENDM
- MACRO Push_M RegList ;; Pushes registers onto stack.
- IRP Reg, <RegList>
- IFIDNI <Reg>, <flags>
- pushf
- ELSE
- push Reg
- ENDIF
- ENDM
- ENDM
- MACRO Zero Reg ;; Zeros any register.
- xor Reg, Reg
- ENDM
-
-
- ERRH equ 255 ; errorlevel if help given
-
-
- ;--------------------------------------------------------------------------;
- ; 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
-
- ;--------------------------------------------------------------------------;
- ; D A T A ;
- ;--------------------------------------------------------------------------;
- LABEL ProgName BYTE
- db 'ask: ', EOS
- LABEL EOL BYTE
- db '.', CR, LF, EOS
- LABEL HelpMsg BYTE
- db CR, LF
- db 'TifaWARE ASK, v1.1a, ', ??Date
- db ' - ask questions in batch files.', CR, LF
- db 'Usage: ask [-options] [msgtxt]', CR, LF, LF
- db 'Options:', CR, LF
- db ' -l = convert response to lower case', CR, LF
- db ' -tn = wait n seconds before timing out', CR, LF
- db ' -u = convert response to upper case', CR, LF
- db ' -? = display this help message', CR, LF, LF
- db 'msgtxt is an optional message to display.', CR, LF, EOS
- LABEL Err1Msg BYTE
- db 'illegal option -- '
- LABEL OptCh BYTE
- db ?
- db EOS
- LABEL Err2Msg BYTE
- db 'time-out value not specified', EOS
- LABEL Err3Msg BYTE
- db 'time-out value too large -- ', EOS
-
- SwitCh db '-' ; char introducing options
- HFlag db 0 ; flag for on-line help
- LFlag db 0 ; flag for lowercase response
- TFlag db 0 ; flag for time-out
- UFlag db 0 ; flag for uppercase response
- Delay dw ? ; time to pause for key
- MsgLen db 0 ; length of message text
- MsgTxt dw ? ; near pointer to message text
- RCode db 0 ; program return code
-
-
- ;--------------------------------------------------------------------------;
- ; L O C A L S T A C K ;
- ;--------------------------------------------------------------------------;
- db 16 dup ("STACK ") ; 128 bytes for local stack
- StackTop = $
-
- ;--------------------------------------------------------------------------;
- ; P R O C E D U R E S ;
- ;--------------------------------------------------------------------------;
- ;---- 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, ;
- ; CX = count of characters left in commandline, ;
- ; DS:SI = pointer to first option to process. ;
- ; Exit: CX = count of characters left _after_ processing, ;
- ; DS:SI = pointer to whitespace _after_ options, ;
- ; Calls: tolower, errmsg, isdigit, atou, fputs ;
- ; Changes: AX, BL, CX, DX, SI, ;
- ; [OptCh], [HFlag], [LFlag], [TFlag], [UFlag], [Delay] ;
- ;--------------------------------------------------------------------------;
- PROC get_Opt
-
- mov [OptCh], al ; save for later
- call tolower ; use only lowercase in cmp.
- cmp al, 'l'
- jz SHORT @@OptL
- cmp al, 't'
- jz SHORT @@OptT
- cmp al, 'u'
- jz SHORT @@OptU
- 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
-
- @@OptL:
- mov [LFlag], 1 ; set lowercase flag
- jmp SHORT @@Fin
-
- @@OptT:
- mov [TFlag], 1 ; set time-out flag
- mov al, [BYTE PTR si] ; get next character
- call isdigit ; if not a digit, trouble!
- jz SHORT @@GetDelay
-
- mov dx, OFFSET Err2Msg ; no delay specified
- call errmsg
- jmp @@OptH
-
- @@GetDelay:
- 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 @@BadDelay ; error in conversion?
- cmp ax, 60*60*12 ; 12 or more hours?
- jae SHORT @@BadDelay ; yes, bad delay
- mov [Delay], ax
- jmp SHORT @@Fin
-
- @@BadDelay:
- push dx
- mov bx, STDERR
- mov dx, OFFSET ProgName
- call fputs
- mov dx, OFFSET Err3Msg
- 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
- jmp SHORT @@OptH
-
- @@OptU:
- mov [UFlag], 1 ; set uppercase flag
-
- @@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 = zero ;
- ; DS:SI = points to CR after commandline. ;
- ; Calls: none ;
- ; Changes: CX, SI ;
- ; [MsgLen], [MsgTxt] ;
- ;--------------------------------------------------------------------------;
- PROC get_Arg
-
- mov [MsgLen], cl ; for safekeeping
- mov [MsgTxt], si
- add si, cx ; adjust so nothing's left
- Zero cl
- mov [BYTE PTR si], EOS ; finish off string
-
- 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, ;
- ; BL, DX (get_Opt), ;
- ; [HFlag], ;
- ; [OptCh], [LFlag], [TFlag], [UFlag], [Delay] (get_Opt), ;
- ; [MsgLen], [MsgTxt] (get_Arg), ;
- ; Direction flag is cleared. ;
- ;--------------------------------------------------------------------------;
- PROC process_CmdLine
-
- cld ; forward, march!
- Zero ch, 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
- mov [HFlag], 1 ; if none, set help flag
- 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 timed-out ;
- ; 255 => on-line help requested ;
- ; else => ASCII value of character pressed. ;
- ; Calls: process_CmdLine, fputs, pause, getchar, tolower, toupper ;
- ; Changes: n/a ;
- ;--------------------------------------------------------------------------;
- main:
- mov sp, OFFSET StackTop ; set up local stack
-
- ;
- ; 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 al, ERRH ; yes, so set return code
- mov bx, STDERR
- mov dx, OFFSET HelpMsg ; point to help message
- call fputs
- jmp SHORT @@Fin ; and jump to end of program
-
- ;
- ; Display any message from commandline then get keypress from user.
- ;
- @@NoHelp:
- mov bx, STDOUT ; everything to stdout
- cmp [MsgLen], 0 ; anything to print out?
- jz SHORT @@NoPrompt ; nope
- mov dx, [MsgTxt]
- call fputs
-
- @@NoPrompt:
- cmp [TFlag], 0 ; need to wait?
- jz SHORT @@KeyIn ; no
- mov ax, [Delay] ; yes, so...
- call pause ; pause
- jz SHORT @@KeyIn ; zf means a key is ready
- Zero al ; set return code to zero
- jmp SHORT @@NewLine
-
- @@KeyIn:
- call getchar
-
- ;
- ; Convert character in AL as necessary. NB: if both '-l' and '-u' options
- ; are specified, the return value will be based on *uppercase* value.
- ;
- cmp [LFlag], 0 ; convert to lowercase?
- jz SHORT @@MaybeUpper ; no
- call tolower
-
- @@MaybeUpper:
- cmp [UFlag], 0 ; convert to uppercase?
- jz SHORT @@NewLine ; no
- call toupper
-
- ;
- ; Add a final newline to keep things neat.
- ;
- @@NewLine:
- mov dx, OFFSET EOL + 1
- call fputs
-
- ;
- ; Ok, let's terminate the program. Return code is already in AL.
- ;
- @@Fin:
- mov ah, 4ch
- int DOS
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; Purpose: Gets current system time, based on DOS's internal clock.
- ; Notes: none
- ; Requires: 8086-class CPU and DOS v1.0 or better.
- ; Entry: n/a
- ; Exit: CL = minutes (0 - 59)
- ; CH = hour (0 - 23)
- ; DL = hundredths of seconds (0 - 99)
- ; DH = seconds (0 - 59)
- ; Calls: none
- ; Changes: CX, DX
- ;-------------------------------------------------------------------------;
- PROC gettime
-
- push ax
- mov ah, 2ch ; MS-DOS get system time function
- int DOS
- pop ax
- ret
-
- ENDP gettime
-
-
- 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
-
- IF @DataSize EQ 0
- Push_M <ax, cx, di>
- ELSE
- Push_M <ax, cx, di, 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 EQ 0
- Pop_M <di, cx, ax>
- ELSE
- Pop_M <es, di, cx, ax>
- ENDIF
- ret
-
- ENDP fputs
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; 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
-
-
- 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_M <bx, dx>
- push dx ; save again calling parameters
- mov bx, STDERR
- mov dx, OFFSET ProgName ; display program name
- call fputs
- pop dx ; recover calling parameters
- call fputs ; display error message
- mov dx, OFFSET EOL
- call fputs
- Pop_M <dx, bx>
- ret
-
- ENDP errmsg
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; 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: Pauses execution for a specified number of seconds or
- ; until a keypress is detected.
- ; Notes: Delay should be less than 12 hours (43200 seconds) to
- ; avoid checks on date rollover yet ensure we haven't
- ; paused too long. Delay is not checked however!
- ; This procedure works by adding the delay to the current
- ; time and waiting until then. If the system clock is
- ; adjusted in meantime, results are unpredictable. I
- ; tried looping and calling gettime(), but that was
- ; inaccurate due to roundoff of hundreths of secs.
- ; Requires: 8086-class CPU and DOS v2.0 or better.
- ; Entry: AX = delay time (in seconds).
- ; Exit: Zero flag set if input ready; cleared otherwise.
- ; Calls: gettime, kbhit
- ; Changes: flags
- ;-------------------------------------------------------------------------;
- PROC pause
-
- Push_M <ax, bx, cx, dx>
- Zero bx
- mov cx, 60 ; 60 secs/min and 60 mins/hour
- Zero dx
- div cx ; now ax = hours and minutes
- mov bh, dl ; and bh = seconds (dh == 0)
- Zero dx
- div cx ; now ax = hours, dx = minutes
- mov ah, al ; hours
- mov al, dl ; minutes
-
- ;
- ; At this point, AX:BX = amount of time to sleep (hh.mm.ss.hs).
- ;
- call gettime ; get current time
- add ax, cx ; compute alarm time
- add bx, dx
- cmp bh, 60 ; too many seconds?
- jb SHORT @@CheckMins ; nope
- sub bh, 60 ; yep, adjust
- inc al
-
- @@CheckMins:
- cmp al, 60 ; too many minutes?
- jb SHORT @@CheckHours ; nope
- sub al, 60 ; yep, adjust
- inc ah
-
- @@CheckHours:
- cmp ah, 24 ; too many hours?
- jb SHORT @@TimeLoop ; nope
- sub ah, 24 ; yep, adjust
-
- ;
- ; Here's the main loop. Check for both keypress and alarm time.
- ; NB: Because of overhead in the code it's possible to overshoot
- ; the alarm time by a few hundreths of a second so check for that.
- ;
- @@TimeLoop:
- call kbhit ; check for user input
- jz SHORT @@Fin ; and abort if present
- call gettime ; get current time
- sub cx, ax ; cx = current time - alarm time
- jz SHORT @@CheckSecs ; if zero, check seconds
- cmp ah, 12 ; adjust if alarm is a.m. ...
- jae SHORT @@TooFar?
- cmp ch, 0 ; and current time is p.m. ...
- jl SHORT @@TooFar? ; (signed comparison!!!)
- sub ch, 24 ; by subtracting 24 hours
-
- @@TooFar?:
- neg cx ; cx = alarm time - current time
- cmp cx, 12 * 256 ; more than 12 hours difference?
- ja SHORT @@Fin ; yep (unsigned comparison!!!)
- jmp @@TimeLoop ; nope (already checked if ==)
-
- @@CheckSecs:
- cmp dx, bx ; wait a few more seconds?
- jb @@TimeLoop ; yep
- or dl, 1 ; no, clear zf
-
- @@Fin:
- Pop_M <dx, cx, bx, ax>
- ret
-
- ENDP pause
-
-
- 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_M <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_M <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
-
-
- 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
-
-
- EVEN
- ;-------------------------------------------------------------------------;
- ; 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_M <ax, di, flags>
- 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_M <di, ax>
- ret
-
- ENDP strlen
-
-
- END
-