home *** CD-ROM | disk | FTP | other *** search
- CGROUP GROUP CODE_SEG, DATA_SEG
- ASSUME CS:CGROUP, DS:CGROUP
-
-
- ;-----------------------------------------------------------------------;
- ; This file contains procedures for working with the keyboard: ;
- ; ;
- ; READ_CHAR Read a character from the keyboard ;
- ; STRING_TO_UPPER Converts a string to upper case ;
- ; CHAR_TO_UPPER Converts a character to upper case ;
- ; READ_STRING Reads in a string of characters ;
- ; READ_DECIMAL Reads a decimal number ;
- ; READ_BYTE Reads a single byte ;
- ; HEX_TO_BYTE Converts to characters to a hex byte ;
- ; CONVERT_HEX_DIGIT Converts a hex digit to a nibble ;
- ;-----------------------------------------------------------------------;
-
-
- BS EQU 8 ;Back space character
- CR EQU 13 ;Carriage return character
- ESC EQU 27 ;Escape character
-
-
- DATA_SEG SEGMENT PUBLIC
- KEY_BOARD_INPUT LABEL BYTE
- CHAR_NUM_LIMIT DB 0 ;Length of input buffer
- NUM_CHARS_READ DB 0 ;Number of characters read
- CHARS DB 80 DUP (0) ;A buffer for keyboard input
- DATA_SEG ENDS
-
- CODE_SEG SEGMENT PUBLIC
-
-
- PUBLIC READ_CHAR
- ;-----------------------------------------------------------------------;
- ; This procedure reads a single character from the keyboard, without ;
- ; echoing it to the screen. ;
- ; ;
- ; Returns: AL Character, or 0 for special keys. ;
- ; AH Extended code of the special key ;
- ;-----------------------------------------------------------------------;
- READ_CHAR PROC NEAR
- MOV AH,7 ;Call for input with no checking
- INT 21h ;for CTRL_BREAK and no echo.
- OR AL,AL ;Is this a special key?
- JNZ DONE_READ_CHAR ;No, then we're all done
- INT 21h ;Yes, then read the extended code
- MOV AH,AL ;Save this in AH
- XOR AL,AL ;Signal that we have an extended code
- DONE_READ_CHAR:
- RET
- READ_CHAR ENDP
-
-
- PUBLIC STRING_TO_UPPER
- ;-----------------------------------------------------------------------;
- ; This procedure converts the string, using the DOS format for strings ;
- ; to all upper-case letters. ;
- ; ;
- ; DS:DX Address of string buffer. ;
- ; ;
- ; Uses: CHAR_TO_UPPER ;
- ;-----------------------------------------------------------------------;
- STRING_TO_UPPER PROC NEAR
- PUSH AX
- PUSH BX
- PUSH CX
- MOV BX,DX
- INC BX ;Point to character count
- MOV CL,[BX] ;Character count in 2nd byte of buffer
- XOR CH,CH ;Clear upper byte of count
- UPPER_LOOP:
- INC BX ;Point to next character in buffer
- MOV AL,[BX] ;Get one character from the string
- CALL CHAR_TO_UPPER ;Convert to upper-case letter
- MOV [BX],AL ;Save this character back to the string
- LOOP UPPER_LOOP
- POP CX
- POP BX
- POP AX
- RET
- STRING_TO_UPPER ENDP
-
-
- PUBLIC CHAR_TO_UPPER
- ;-----------------------------------------------------------------------;
- ; This procedure converts a single character to upper case. ;
- ; ;
- ; On entry: AL Character to convert ;
- ; Returns: AL Upper-case version of the letter ;
- ;-----------------------------------------------------------------------;
- CHAR_TO_UPPER PROC NEAR
- CMP AL,'a' ;Is this a lower-case letter?
- JB NOT_LOWER ;No, then we're all done
- CMP AL,'z' ;Is this a lower-case letter?
- JA NOT_LOWER ;No, then we're all done
- ADD AL,'A'-'a' ;Convert to upper-case letter
- NOT_LOWER:
- RET
- CHAR_TO_UPPER ENDP
-
-
- PUBLIC READ_STRING
- EXTRN WRITE_CHAR:NEAR
- ;-----------------------------------------------------------------------;
- ; This procedure performs a function very similar to the DOS 0AH ;
- ; function. But this function will return a special character if a ;
- ; function or key pad key is pressed -- no return for these keys. And ;
- ; ESC will erase the input and start over again. ;
- ; ;
- ; DS:DX Address for keyboard buffer. The first byte must ;
- ; contain the maximum number of characters to read (plus ;
- ; one for the return). And the second byte will be used ;
- ; by this procedure to return the number of characters ;
- ; actually read. ;
- ; 0 No characters read ;
- ; -1 One special character read ;
- ; otherwise number actually read (not including ;
- ; return key). ;
- ; ;
- ; Uses: READ_CHAR, BACK_SPACE, WRITE_CHAR ;
- ;-----------------------------------------------------------------------;
- READ_STRING PROC NEAR
- PUSH AX
- PUSH BX
- PUSH SI
- MOV SI,DX ;Use SI for index register and
- START_OVER:
- MOV BX,2 ;BX for offset to beginning of buffer
- CALL READ_CHAR
- OR AL,AL ;Is character extended ASCII?
- JZ EXTENDED ;Yes, then handle it.
- NOT_EXTENDED: ;Extnd char is error unless buff empty
- CMP AL,CR ;Is this a carriage return?
- JE END_INPUT ;Yes, we are done with input
- CMP AL,BS ;Is it a back space character?
- JNE NOT_BS ;Nope
- CALL BACK_SPACE ;Yes, delete character
- CMP BL,2 ;Is buffer empty?
- JE START_OVER ;Yes, can now read extended ASCII again
- JMP SHORT READ_NEXT_CHAR ;No, continue reading normal characters
- NOT_BS: CMP AL,ESC ;Is it an ESC -- purge buffer?
- JE PURGE_BUFFER ;Yes, then purge the buffer
- CMP BL,[SI] ;Check to see if buffer is full
- JA BUFFER_FULL ;Buffer is full
- MOV [SI+BX],AL ;Else save char in buffer
- INC BX ;Point to next free character in buffer
- PUSH DX
- MOV DL,AL ;Echo character to screen
- CALL WRITE_CHAR
- POP DX
- READ_NEXT_CHAR:
- CALL READ_CHAR
- OR AL,AL ;An extended ASCII char is not valid
- ;when the buffer is not empty.
- JNZ NOT_EXTENDED ;Char is valid
- ;Char is extended, signal error
-
- ;-----------------------------------------------;
- ; Signal an error condition by sending a beep ;
- ; character to the display: chr$(7). ;
- ;-----------------------------------------------;
- SIGNAL_ERROR:
- PUSH DX
- MOV DL,7 ;Sound the bell by writing chr$(7)
- MOV AH,2
- INT 21H
- POP DX
- JMP SHORT READ_NEXT_CHAR ;Now read next character.
-
- ;-----------------------------------------------;
- ; Empty the string buffer and erase all the ;
- ; characters displayed on the screen. ;
- ;-----------------------------------------------;
- PURGE_BUFFER:
- PUSH CX
- MOV CL,[SI] ;Backspace over maximum number of
- XOR CH,CH
- PURGE_LOOP: ;characters in buffer. BACK_SPACE
- CALL BACK_SPACE ;will keep the cursor from moving too
- LOOP PURGE_LOOP ;far back.
- POP CX
- JMP START_OVER ;Can now read extended ASCII characters
- ;since the buffer is empty
-
- ;-----------------------------------------------;
- ; The buffer was full, so can't read another ;
- ; character. Send a beep to alert user of ;
- ; buffer full condition. ;
- ;-----------------------------------------------;
- BUFFER_FULL:
- JMP SHORT SIGNAL_ERROR ;If buffer full, just beep.
-
- ;-----------------------------------------------;
- ; Read the extended ASCII code and place this ;
- ; in the buffer as the only character, then ;
- ; return -1 as the number of characters read. ;
- ;-----------------------------------------------;
- EXTENDED:
- MOV [SI+2],AH ;Place extended code into the buffer
- MOV BL,0FFH ;Num chars read = -1 for special
- JMP SHORT END_STRING
-
- ;-----------------------------------------------;
- ; Save the count of the number of characters ;
- ; read and return. ;
- ;-----------------------------------------------;
- END_INPUT: ;Done with input.
- SUB BL,2 ;Count of characters read
- END_STRING:
- MOV [SI+1],BL ;Return number of chars read
- POP SI
- POP BX
- POP AX
- RET
- READ_STRING ENDP
-
-
- PUBLIC BACK_SPACE
- EXTRN WRITE_CHAR:NEAR
- ;-----------------------------------------------------------------------;
- ; This procedure deletes characters, one at a time, from the buffer and ;
- ; the screen when the buffer is not empty. BACK_SPACE simply returns ;
- ; when the buffer is empty. ;
- ; DS:SI+BX most recent character still in buffer. ;
- ; ;
- ; Uses: WRITE_CHAR ;
- ;-----------------------------------------------------------------------;
- BACK_SPACE PROC NEAR ;Delete one character
- PUSH AX
- PUSH DX
- CMP BX,2 ;Is buffer empty
- JE END_BS ;Yes, read the next character
- DEC BX ;remove one character from buffer
- MOV AH,2 ;Remove character from screen
- MOV DL,BS
- INT 21H
- MOV DL,20H ;Write space there
- CALL WRITE_CHAR
- MOV DL,BS ;Back-up again
- INT 21H
- END_BS: POP DX
- POP AX
- RET
- BACK_SPACE ENDP
-
-
- PUBLIC READ_DECIMAL
- ;-----------------------------------------------------------------------;
- ; This procedure takes the output buffer of READ_STRING and converts ;
- ; the string of decimal digits to a word. ;
- ; ;
- ; AX Word converted from decimal ;
- ; CF Set if error, clear if no error ;
- ; ;
- ; Uses: READ_STRING ;
- ; Reads: KEY_BOARD_INPUT, etc. ;
- ;-----------------------------------------------------------------------;
- READ_DECIMAL PROC NEAR
- PUSH BX
- PUSH CX
- PUSH DX
- MOV CHAR_NUM_LIMIT,6 ;Max number is 5 digits (65535)
- LEA DX,KEY_BOARD_INPUT
- CALL READ_STRING
- MOV CL,NUM_CHARS_READ ;Get number of characters read
- XOR CH,CH ;Set upper byte of count to zero
- CMP CL,0 ;Return error if no characters read
- JLE BAD_DECIMAL_DIGIT ;No chars read, signal error
- XOR AX,AX ;Start with number set to zero
- XOR BX,BX ;Start at beginning of string
- CONVERT_DIGIT:
- MOV DX,10 ;Multiply number by 10
- MUL DX ;Multiply AX by 10
- JC BAD_DECIMAL_DIGIT ;CF set if MUL overflowed one word
- MOV DL,CHARS[BX] ;Get the next digit
- SUB DL,'0' ;And convert to a nibble (4 bits)
- JS BAD_DECIMAL_DIGIT ;Bad digit if < 0.
- CMP DL,9 ;Is this a bad digit?
- JA BAD_DECIMAL_DIGIT ;Yes
- ADD AX,DX ;No, so add it to number
- INC BX ;Point to next character
- LOOP CONVERT_DIGIT ;Get the next digit
- DONE_DECIMAL:
- POP DX
- POP CX
- POP BX
- RET
- BAD_DECIMAL_DIGIT:
- STC ;Set carry to signal error
- JMP DONE_DECIMAL
- READ_DECIMAL ENDP
-
-
- PUBLIC READ_BYTE
- ;-----------------------------------------------------------------------;
- ; This procedure reads either a single ASCII character. This is just ;
- ; a test version of READ_BYTE. ;
- ; ;
- ; Returns byte in AL Character code (unless AH = 0) ;
- ; AH 1 if read ASCII char ;
- ; 0 if no characters read ;
- ; -1 if read a special key ;
- ; ;
- ; Uses: HEX_TO_BYTE, STRING_TO_UPPER, READ_STRING ;
- ; Reads: KEY_BOARD_INPUT, etc. ;
- ;-----------------------------------------------------------------------;
- READ_BYTE PROC NEAR
- PUSH DX
- MOV CHAR_NUM_LIMIT,3 ;Allow only two characters (plus enter)
- LEA DX,KEY_BOARD_INPUT
- CALL READ_STRING
- CMP NUM_CHARS_READ,1 ;See how many characters
- JE ASCII_INPUT ;Just one, treat as ASCII character
- JB NO_CHARACTERS ;Only enter key hit
- CMP NUM_CHARS_READ,0FFH ;Special function key?
- JE SPECIAL_KEY ;Yes.
- CALL STRING_TO_UPPER ;No, convert string to upper-case
- LEA DX,CHARS ;Address of string to convert
- CALL HEX_TO_BYTE ;Convert string from hex to byte
- JC NO_CHARACTERS ;Error, so return 'no characters read'
- MOV AH,1 ;Signal read one character
- DONE_READ:
- POP DX
- RET
- NO_CHARACTERS:
- XOR AH,AH ;Set to 'no characters read'
- JMP DONE_READ
- ASCII_INPUT:
- MOV AL,CHARS ;Load character read
- MOV AH,1 ;Signal read one character
- JMP DONE_READ
- SPECIAL_KEY:
- MOV AL,CHARS[0] ;Return the scan code
- MOV AH,0FFH ;Signal special key with -1
- JMP DONE_READ
- READ_BYTE ENDP
-
-
- PUBLIC HEX_TO_BYTE
- ;-----------------------------------------------------------------------;
- ; This procedure converts the two characters at DS:DX from hex to one ;
- ; byte. ;
- ; ;
- ; DS:DX Address of two characters for hex number ;
- ;Returns: ;
- ; AL Byte ;
- ; CF Set for error, clear if no error ;
- ; AH changed ;
- ; ;
- ; Uses: CONVERT_HEX_DIGIT ;
- ;-----------------------------------------------------------------------;
- HEX_TO_BYTE PROC NEAR
- PUSH BX
- PUSH CX
- MOV BX,DX ;Put address in BX for indirect addr
- MOV AL,[BX] ;Get first digit
- CALL CONVERT_HEX_DIGIT
- JC BAD_HEX ;Bad hex digit if carry set
- MOV CX,4 ;Now multiply by 16
- SHL AL,CL
- MOV AH,AL ;Retain a copy
- INC BX ;Get second digit
- MOV AL,[BX]
- CALL CONVERT_HEX_DIGIT
- JC BAD_HEX ;Bad hex digit if carry set
- OR AL,AH ;Combine two nibbles
- CLC ;Clear carry for no error
- DONE_HEX:
- POP CX
- POP BX
- RET
- BAD_HEX:
- STC ;Set carry for error
- JMP DONE_HEX
- HEX_TO_BYTE ENDP
-
-
- PUBLIC CONVERT_HEX_DIGIT
- ;-----------------------------------------------------------------------;
- ; This procedure converts a character from ASCII (hex) to a nibble (4 ;
- ; bits). ;
- ; ;
- ; AL character to convert ;
- ; Returns: AL nibble ;
- ; CF Set for error, cleared otherwise ;
- ;-----------------------------------------------------------------------;
- CONVERT_HEX_DIGIT PROC NEAR
- CMP AL,'0' ;Is it a legal digit?
- JB BAD_DIGIT ;Nope
- CMP AL,'9' ;Not sure yet
- JA TRY_HEX ;Might be hex digit
- SUB AL,'0' ;Is decimal digit, convert to nibble
- CLC ;Clear the carry, no error
- RET
- TRY_HEX:
- CMP AL,'A' ;Not sure yet
- JB BAD_DIGIT ;Not hex
- CMP AL,'F' ;Not sure yet
- JA BAD_DIGIT ;Not hex
- SUB AL,'A'-10 ;Is hex, convert to nibble
- CLC ;Clear the carry, no error
- RET
- BAD_DIGIT:
- STC ;Set the carry, error
- RET
- CONVERT_HEX_DIGIT ENDP
-
-
- CODE_SEG ENDS
-
- END