'Check for keypress without blocking if no key was pressed
I'm creating an application to view the current time and I created a loop to update the time each second. The loop looks like this
UPDATE:
;The code to be re-executed
JMP UPDATE
but I cant end it. When I use
MOV AH, 00H
INT 21H
to capture any pressed key, the application stops and waits for a keypress. I don't want that to happen; the application should go normally and end the loop when the user hits escape
What is the best way to do this?
Solution 1:[1]
Whenever during DOS programming you are looking for some service, have a look at Ralf Brown's interrupt list.
Particularly, keyboard related services fall under the int 16h
category.Int 16/AH=01h
is CHECK FOR KEYSTROKE which is exactly what you need: after it returns, the ZF
1 is set2 if no keystroke was available; also AL
and AH
contain the ASCII and scan code of the key pressed.
Alone however it is not enough as it doesn't remove the keystroke from the buffer, so if the user presses ABESC, using CHECK FOR KEYSTROKE alone would always return that A is available.
You can use Int 16/AH=00h
, GET KEYSTROKE to read and remove a keystroke from the buffer without echoing it.
You can also use Int 21/AH=01h
to read a character and echo it3, note that despite what is stated in your question, Int 21/AH=00h
is totally unrelated to this task as it is TERMINATE PROGRAM.
Finally the ASCII code for ESC is 27 or 1bh.
Here a sample COM program that loops until ESC is pressed.
BITS 16
ORG 100h
_loop:
;
; L O O P S T U F F
;
;Show a greeting message
mov ah, 09h
mov dx, strGreetings
int 21h
;
; K E Y S C H E C K
;
;Check for a keystroke
mov ah, 01h
int 16h
jz _loop ;ZF is set if no keystroke available
;A keystroke is present, remove it from the buffer
;so that we always check the last key pressed by the user
xor ah, ah
int 16h
;AL = ASCII code
;AH = Scancode
;Check the key was ESC
cmp al, ESC_ASCII_CODE
jne _loop
;
; T E R M I N A T I O N
;
mov ax, 4c00h
int 21h
;[ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
; [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
;[ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
;
;D A T A
;
strGreetings db "Hello!", 13, 10, 24h
;[ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
; [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
;[ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ] [ o ]
;
;E Q U A L S
;
ESC_ASCII_CODE EQU 27
1 The zero flag, you can jump depending on it with jz/je
(jump if it is set) or jnz/jne
(jump if it is clear).
2 Think of this as: Zero was set because there was zero keystrokes.
3 Though I believe that's not really appropriate for non printable chars.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Margaret Bloom |