'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 ZF1 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