惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

faryou的博客

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】再谈栈 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):背包DP——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):简单动规问题——程序设计思路与代码实现 【算法教程】【C/C++】递推——程序设计思路与代码实现 【算法教程】【C/C++】三分算法——程序设计思路与代码实现 【算法教程】【C/C++】二分答案——程序设计思路与代码实现 【算法教程】【C/C++】二分查找——程序设计思路与代码实现 【算法教程】【C/C++】贪心算法——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快排——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快速幂——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:进制转换——程序设计思路与代码实现 一文弄懂C++中的自定义函数 faryou的博客-2024年度总结
【汇编&硬件】键盘读取中断的具体实现
作者: faryou · 2026-02-17 · via faryou的博客

前言

int 9h是8086系统中键盘中断的中断服务程序,用于处理键盘输入。其功能包括读取键盘扫描码、处理特殊键(如Shift、Ctrl等)、将扫描码转换为ASCII码以及设置键盘缓冲区等。它与面向用户的int 16h相互配合。前面我们说过int 9h涉及到硬件的处理,所以当时没有尝试自己编写。下面我们尝试自己实现这个中断。

代码实现

; 定义段寄存器
code segment
    assume cs:code
 
; 键盘中断服务程序(替代int 9h)
keyboard_int proc far
    push ax
    push bx
    push cx
    push dx
    push si
    push di
    push es
    push ds ; 保存所有寄存器状态
 
    ; 1. 读取键盘扫描码(从端口60h读取)
    in al, 60h ; 读取扫描码到AL(通码:按键按下,断码:按键松开,断码=通码+80h)
 
    ; 2. 向8259A发送中断结束信号(EOI),允许后续中断
    mov al, 20h ; EOI命令字
    out 20h, al ; 发送到主8259A
 
    ; 3. 处理扫描码(此处简化处理:仅响应部分按键,忽略断码和特殊键)
    cmp al, 80h ; 判断是否为断码(若AL>=80h,说明按键松开,不处理)
    jae int_end ; 是断码则直接结束
 
    ; 4. 扫描码转ASCII码(简化映射表,仅举例常用键)
    mov bx, offset scancode_to_ascii ; BX指向映射表
    xlat ; AL = [BX + AL](根据扫描码获取ASCII码,0表示无对应ASCII)
 
    ; 5. 若有有效ASCII码,存入键盘缓冲区(简化,实际需检查缓冲区状态)
    cmp al, 0
    je int_end ; 无对应ASCII,结束
 
    ; 此处仅演示,实际缓冲区操作需更复杂(如使用BIOS数据区的键盘缓冲区)
    mov ah, 0eh ; 调用BIOS中断,在屏幕上显示字符(模拟输入效果)
    int 10h
 
int_end:
    pop ds
    pop es
    pop di
    pop si
    pop dx
    pop cx
    pop bx
    pop ax ; 恢复寄存器状态
    iret ; 中断返回
keyboard_int endp
 
; 扫描码到ASCII码的简化映射表(仅部分键,通码对应)
; 索引:扫描码(通码),值:ASCII码(0表示无对应)
scancode_to_ascii db 0 ; 00h(无键)
                  db 27 ; 01h(Esc,ASCII 27)
                  db '1' ; 02h(1键)
                  db '2' ; 03h(2键)
                  db '3' ; 04h(3键)
                  db '4' ; 05h(4键)
                  db '5' ; 06h(5键)
                  db '6' ; 07h(6键)
                  db '7' ; 08h(7键)
                  db '8' ; 09h(8键)
                  db '9' ; 0Ah(9键)
                  db '0' ; 0Bh(0键)
                  db '-' ; 0Ch(-键)
                  db '=' ; 0Dh(=键)
                  db 8 ; 0Eh(Backspace,ASCII 8)
                  db 9 ; 0Fh(Tab,ASCII 9)
                  db 'q' ; 10h(Q键)
                  db 'w' ; 11h(W键)
                  db 'e' ; 12h(E键)
                  db 'r' ; 13h(R键)
                  db 't' ; 14h(T键)
                  db 'y' ; 15h(Y键)
                  db 'u' ; 16h(U键)
                  db 'i' ; 17h(I键)
                  db 'o' ; 18h(O键)
                  db 'p' ; 19h(P键)
                  ; 更多键的映射可继续添加...
 
; 安装中断向量(将自定义中断服务程序地址写入中断向量表)
install proc
    cli ; 关中断,防止安装过程被打断
    mov ax, 0
    mov es, ax ; ES指向中断向量表段(0段)
    mov di, 9*4 ; int 9h的向量地址:9*4=36(0000:0024)
    mov ax, offset keyboard_int ; 中断服务程序偏移地址
    stosw ; 写入偏移量到向量表
    mov ax, cs ; 中断服务程序段地址(当前代码段)
    stosw ; 写入段地址到向量表
    sti ; 开中断
    ret
install endp
 
; 主程序:安装中断后等待(实际使用中需保持程序运行以响应中断)
main:
    call install ; 安装自定义int 9h中断
    jmp $ ; 无限循环,等待中断
 
code ends
    end main

代码说明

  1. 中断服务程序结构:遵循中断处理规范,先保存所有寄存器,处理完成后恢复并通过 iret 返回。
  2. 扫描码读取:从端口 60h 读取键盘扫描码(通码/断码),通码表示按键按下,断码(通码+80h)表示按键松开。
  3. 中断结束信号:向8259A中断控制器发送 EOI (20h),允许后续中断。
  4. 扫描码转ASCII:通过映射表将常用按键的通码转换为对应的ASCII码(简化处理,实际需考虑Shift、CapsLock等修饰键)。
  5. 缓冲区与输出:简化演示中直接调用BIOS中断显示字符,实际应将数据存入键盘缓冲区。
  6. 中断安装:修改中断向量表(0段)中int 9h对应的地址,指向自定义服务程序。