在 DOS 编程期间,如果您正在寻找一些服务,请查看Ralf Brown's interrupt list。
特别是,与键盘相关的服务属于 int 16h 类别。
Int 16/AH=01h 是 CHECK FOR KEYSTROKE,这正是您所需要的:返回后,ZF1 是 set2 如果没有可用的击键; AL 和 AH 还包含所按下键的 ASCII 码和扫描码。
但是它是不够的,因为它不会从缓冲区中删除击键,所以如果用户按下 ABESC ,单独使用 CHECK FOR KEYSTROKE 将始终返回 A 可用。
您可以使用Int 16/AH=00h, GET KEYSTROKE 从缓冲区中读取和删除击键而不回显它。
您也可以使用Int 21/AH=01h 读取一个字符并回显它3,注意尽管您的问题中说明了,Int 21/AH=00h 与这个任务是终止程序。
ESC 的 ASCII 码最后是 27 或 1bh。
这里是一个循环的示例 COM 程序,直到按下 ESC。
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 零标志,你可以根据它使用jz/je(设置时跳转)或jnz/jne(明确时跳转)来跳转。
2 将其视为:设置为零是因为按键次数为零。
3 虽然我认为这并不适合不可打印的字符。