INT 21h AH=07h waits for a key and returns it in AL, and that is all: nothing is echoed and no key is special. Ctrl+C comes back as 03h. It is the read for programs that handle every key themselves: editors, games, menus, and anything that has hooked a vector and must not be stopped halfway.
MOV SI, OFFSET KEYS1CALL STUFF1 ; Ctrl+C, then F1MOV AH, 07h ; DOS: read a key, no echo, no Ctrl+C checkINT 21h ; AL = 03h: Ctrl+C, an ordinary key hereCALL HEX2MOV DL, " "MOV AH, 02h ; DOS: print the character in DLINT 21hMOV AH, 07hINT 21h ; AL = 00h: a special key, the scan code followsCALL HEX2MOV DL, " "MOV AH, 02h ; DOS: print the character in DLINT 21hMOV AH, 07hINT 21h ; AL = 3Bh: the scan code of F1CALL HEX2KEYS1 DW 2E03h, 3B00h, 0 ; Ctrl+C, F1: scan code and ASCIISTUFF1 PROC NEAR ; "type" the keys at DS:SI: words, 0 ends the listCLDST1:LODSW ; AH = scan code, AL = ASCIITEST AX, AXJZ ST2MOV CX, AX ; CH = scan code, CL = ASCIIMOV AH, 05h ; BIOS: store a keystroke in the keyboard bufferINT 16hJMP ST1ST2:RETSTUFF1 ENDPHEX2 PROC NEAR ; print AL as two hex digitsPUSH AXMOV CL, 4SHR AL, CL ; the high digit firstCALL NIB1POP AXAND AL, 0Fh ; then the low oneCALL NIB1RETHEX2 ENDPNIB1 PROC NEAR ; print AL (0-15) as one hex digitADD AL, "0"CMP AL, "9"JBE NIB2ADD AL, 7 ; 10-15 become "A"-"F"NIB2:MOV DL, ALMOV AH, 02hINT 21hRETNIB1 ENDP
The example puts Ctrl+C (scan code 2Eh, ASCII 03h) and F1 (scan code 3Bh, ASCII 0) into the BIOS buffer through INT 16h AH=05h, then reads three bytes. Ctrl+C is just a byte. F1 takes two calls: the first returns 0, which means "a special key", the second its scan code. A key loop handles that like this:
MOV AH, 07h ; DOS: read a key, no echoINT 21hTEST AL, AL ; 0: a special keyJNZ PLAIN1MOV AH, 07h ; read again: the scan codeINT 21h; AL = 48h up, 50h down, 4Bh left, 4Dh right, 3Bh F1 ...PLAIN1:
| Service | Waits for a key | Echo | Ctrl+C |
|---|---|---|---|
INT 21h AH=01h | yes | yes | ^C, INT 23h: normally the end of the program |
INT 21h AH=06h (DL = FFh) | no: ZF = 1 when none is waiting | no | returned as 03h |
INT 21h AH=07h | yes | no | returned as 03h |
INT 21h AH=08h | yes | no | ^C, INT 23h |
INT 21h AH=0Ah | for a whole line, up to Enter | yes | ^C, INT 23h |
Pitfalls
A program that reads only with 07h has switched off the user's emergency exit, so it should offer one of its own, usually Esc (1Bh). The call still reads handle 0: with input redirected from a file it returns the file's bytes, and a program waiting for a particular key may wait past the end of the file. For the keyboard itself, whatever the redirection, use INT 16h AH=00h, which also returns the scan code of every key in AH in one call.