You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86汇编直接读取Port 60h按键异常问题求助

问题分析与解决思路

你的代码核心问题在于混用了直接端口读取和BIOS键盘中断函数,同时没有正确处理键盘控制器的输出缓冲区残留数据,导致按键事件逻辑混乱。

具体问题点

  1. 多余的int 16h ah=0调用:你已经直接读取Port 60h获取键盘扫描码,但每次匹配到按下码后又调用BIOS的键盘读取函数,这会让BIOS取走键盘缓冲区的事件,和你的端口读取逻辑冲突,导致后续按键事件被BIOS拦截,你的代码无法读到。
  2. 未清空键盘输出缓冲区:键盘控制器的Port 60h输出缓冲区可能存在多个待读取的字节(比如前一个按键的松开码、新按键的按下码),你的代码只读取一次就处理,残留的字节会干扰下一次读取。
  3. 无效的loop指令:你的逻辑是处理完按键后跳回循环,cx的计数完全没用,反而可能导致循环提前终止。

修正方案

  1. 移除所有mov ah,0; int 16h调用,完全用端口读取逻辑处理按键。
  2. 读取扫描码时,循环清空输出缓冲区:通过检查Port 64h的第0位(输出缓冲区满标志),确保读完所有待处理的扫描码。
  3. 去掉无用的loop指令,改用无限循环处理按键。

修正后的代码示例

mov ah, 0
mov al, 2
int 10h         ; 设置文本模式

ll:
    ; 循环清空键盘输出缓冲区,确保读取最新的扫描码
    check_buffer:
        in al, 64h
        test al, 01h       ; 检查输出缓冲区是否有数据(第0位为1表示有)
        jz check_buffer    ; 缓冲区为空则等待
        in al, 60h         ; 读取扫描码
        mov dl, al
        test al, 80h       ; 检查是否是松开码(最高位为1)
        jnz ll             ; 松开码直接丢弃,继续等待按下

    ; 匹配按下的按键扫描码
    cmp dl, 48h
    je print_msg1
    cmp dl, 50h
    je print_msg2
    cmp dl, 4Dh
    je print_msg3
    cmp dl, 4Bh
    je print_msg4
    jmp ll                 ; 未匹配的按键,回到循环

print_msg1:
    mov dx, offset msg1
    mov ah, 9
    int 21h
    jmp ll

print_msg2:
    mov dx, offset msg2
    mov ah, 9
    int 21h
    jmp ll

print_msg3:
    mov dx, offset msg3
    mov ah, 9
    int 21h
    jmp ll

print_msg4:
    mov dx, offset msg4
    mov ah, 9
    int 21h
    jmp ll

d:
    ; 这里可以添加程序退出逻辑,比如 mov ah,4Ch; int 21h

额外说明

  • 键盘扫描码:按下键时返回的是00h-7Fh的扫描码,松开时返回对应的扫描码+80h,你的代码只需要处理按下事件,所以遇到松开码直接丢弃即可。
  • Port 64h是键盘控制器的状态端口,第0位表示输出缓冲区(Port60h)是否有数据可读,第1位表示输入缓冲区是否满。

内容的提问来源于stack exchange,提问作者zizo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:47:18