【问题标题】:Check for keypress without blocking if no key was pressed如果没有按键被按下,则检查按键而不阻塞
【发布时间】:2016-08-03 23:58:26
【问题描述】:

我正在创建一个应用程序来查看当前时间,并创建了一个循环来每秒更新时间。循环看起来像这样

UPDATE:
;The code to be re-executed
JMP UPDATE

但我无法结束它。当我使用

MOV AH, 00H
INT 21H

要捕获任何按下的键,应用程序会停止并等待按键。我不希望这种情况发生;当用户点击退出时,应用程序应该正常运行并结束循环

最好的方法是什么?

【问题讨论】:

  • 查找 DOS 系统调用以轮询输入,而不是进行阻塞读取。我认为它有一些东西,但 DOS 对我来说已经过时且无趣,所以我不知道究竟是什么。或者在按下 ESC 时自行挂钩键盘中断以设置一个标志(在内存中),并在每次循环迭代时检查该标志。顺便说一句,感谢您保持问题简短而不是发布一个不相关的大代码转储。这是一个问得很好的问题,只是对我个人来说并不感兴趣。我想它甚至值得一票。
  • 改为查看INT 16H。它具有“检查是否按下某个键”的功能。

标签: assembly dos x86-16


【解决方案1】:

在 DOS 编程期间,如果您正在寻找一些服务,请查看Ralf Brown's interrupt list

特别是,与键盘相关的服务属于 int 16h 类别。
Int 16/AH=01hCHECK FOR KEYSTROKE,这正是您所需要的:返回后,ZF1set2 如果没有可用的击键; ALAH 还包含所按下键的 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 虽然我认为这并不适合不可打印的字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    相关资源
    最近更新 更多