汇编语言中如何清空键盘缓冲区解决按键响应延迟问题
问题解决方案
你判断的延迟原因完全准确:PC键盘长按时会触发自动重复输入,持续向BIOS键盘环形缓冲区(位于BIOS数据段,最多缓存15个按键事件)写入数据,你每次循环仅读取1个按键,剩余事件持续积压就会导致响应越来越慢。
没有专用中断可以直接一键清空键盘缓冲区,但有两种成熟的DOS实模式下清空缓冲区的实现方案,适配你当前的汇编代码:
方案1:循环读取丢弃所有待处理按键(兼容性最佳,推荐)
利用int 16h的两个功能组合实现:
AH=01h, int 16h:检测缓冲区是否有未读按键,ZF=0代表存在待读按键AH=00h, int 16h:从缓冲区读取一个按键,直接丢弃即可
循环执行上述逻辑直到缓冲区为空(ZF=1),不需要操作额外内存段,所有DOS兼容环境都可运行。
方案2:直接重置缓冲区指针(执行效率最高)
BIOS键盘缓冲区的头、尾指针存放在0040:001A和0040:001C两个内存地址,当两个指针值相等时,BIOS会判定缓冲区为空。直接将两个指针都设为缓冲区起始偏移1Eh即可瞬间清空缓冲区,不需要循环。
注意:修改指针时需要临时关中断,避免键盘中断在修改过程中写入新数据导致指针不一致。
适配你代码的修改示例
把原有key过程替换为如下实现(采用方案2,同时兼容你原有逻辑):
proc key push bp mov bp,sp push ax push bx push cx push si push dx push di push es ; 新增保存段寄存器,用于访问BIOS数据段 mov [hi],0 ; 清空键盘缓冲区 mov ax, 40h mov es, ax cli mov es:[1Ah], word ptr 1Eh mov es:[1Ch], word ptr 1Eh sti ; 原有按键检测逻辑 mov ah, 01 int 16h jz L3 mov ah, 00h int 16h cmp al, 68h jne L3 mov [hi],1 L3: pop es ; 恢复段寄存器 pop di pop dx pop si pop cx pop bx pop ax pop bp ret endp key
额外优化建议
你现有代码每次主循环都切换一次13h图形模式、再切回2号文本模式,属于完全不必要的开销,会额外加重延迟。只需要在程序开头初始化时设置一次你需要的显示模式即可,不需要在循环里反复切换。
内容的提问来源于stack exchange,提问作者maya
相关产品推荐
相关产品推荐

