《汇编语言》- 读书笔记 - 第15章-外中断
《汇编语言》- 读书笔记 - 第15章-外中断
- 15.1 接口芯片和端口
- 15.2 外中断信息
- 1. 可屏蔽中断(Maskable Interrupt)
- 2. 不可屏蔽中断(Non-Maskable Interrupt)
- 设计思想
- 15.3 PC 机键盘的处理过程
- 1. 键盘输入
- 2. 引发 9 号中断
- 3. 执行 int 9 中断例程
- 15.4 编写int9 中断例程
- 编程
- 思路
- 代码
- 检测点 15.1
- 15.5 安装新的 int 9 中断例程
- 分析
- 代码
- 运行效果
- 实验 15 安装新的 int9 中断例程
CPU通过中断机制得知外部输入事件,并通过I/O接口与数据总线实现与外设的数据交换,从而实现对外设输入的有效处理。
CPU 对外设输入的通常处理方法:
- 外设的输入送入端口;
- 向 CPU 发出外中断(可屏蔽中断)信息;
CPU检测到可屏蔽中断信息;
3.1. 如果IF=1,CPU 在执行完当前指令后响应中断,执行相应的中断例程;- 可在中断例程中实现对外设输入的处理。
端口和中断机制,是 CPU 进行 I/O 的基础。
15.1 接口芯片和端口
CPU 通过端口和外部设备进行联系。
15.2 外中断信息
外部设备 在完成一系列自己的工作后,需要将产生的数据或状态发给CPU处理时,就会触发外中断
- 中断信息的发送过程大致如下:
-
中断请求信号:
外设芯片在适当时候会通过自身的中断输出引脚向主板上的中断控制器发送中断请求信号,这通常表现为一个电信号的变化。例如在8086体系结构中,外设可以通过INTR(Interrupt Request)线向CPU发出中断请求。 -
中断控制器:
主板上的中断控制器(如Intel 8259A可编程中断控制器)负责接收来自多个外设的中断请求,并根据它们的优先级和中断向量进行管理。中断控制器会将有效的中断请求打包并通过IRQ(Interrupt Request Line)线传输到CPU。 -
CPU响应中断:
当CPU在执行完当前指令后检查中断请求线时,如果发现有中断请求存在,它会暂停当前任务,保存现场,然后通过读取中断向量表(IVT)获取中断服务程序(ISR)的地址,跳转到相应的处理程序执行中断处理。 -
线路连接:
中断请求信号的传送是通过主板上的硬件连线完成的。例如在8086/8088系统中,外设与CPU间的中断请求线和中断响应线(INTA#)是主板上的物理连接线,它们属于系统总线的一部分,通过这些线路上的电信号变化来进行中断请求和响应的通讯。
注意,随着技术的发展,更现代的计算机系统可能采用了更为复杂和高级的中断控制器和总线标准,但核心原理仍然是外设通过特定线路发送中断信号给CPU,并由CPU依据一定的优先级策略来响应和处理中断。
1. 可屏蔽中断(Maskable Interrupt)
可屏蔽中断 | CPU在收到可屏蔽中断时会根据 CF 的状态来决定:执行完当前指令后是否响应。
| IF 状态 | 响应 | 不响应 |
|---|---|---|
| IF = 1 | ✅ | |
| IF = 0 | ✅ |
- 中断过程
可屏蔽中断的中断过程除了中断类型码是通过数据总线从外部传进CPU的,其它与内中断相同。
我们可以通过指令(STI, CLI)设置IF来控制是否响应可屏蔽中断。
| ———— 指 令 ———— | — 功 能 — | 描述 |
|---|---|---|
cli(Clear Interrupt Flag) | IF=0 禁止中断 | CPU执行cli将IF=0后,仅保留对不可屏蔽中断(NMI)的响应,直至遇到STI指令为止。此操作有助于保护在执行重要且不能被打断的代码时,不被中断处理程序打乱。 例如: 在更改栈指针(SS:SP)时,需要防止因中断处理程序介入而破坏栈的状态。 |
sti(Set Interrupt Flag) | IF=1 允许中断 | CPU执行sti将IF=1后,重新开启中断响应功能。CPU会再次响应挂起的中断请求,恢复正常的中断处理流程。这对于完成关键区域操作后恢复系统的正常中断响应至关重要。 |
- 在IF=0期间,中断请求不会丢失,但会被延迟处理,等待CPU重新打开中断响应后,按照中断控制器维护的队列顺序逐一处理。是否超时以及超时后的处理方法取决于设备本身的特性以及操作系统的调度策略。
硬件中断控制器(如Intel 8259A可编程中断控制器)负责管理和维持中断请求的排队。 CLI与STI结合运用,构建短暂的中断防护区域,确保其间代码免受外部中断影响,待关键操作完成后通过STI恢复中断响应,保障系统并发处理能力和实时响应性能。在多任务OS中,内核常在切换进程环境、管控硬件资源等关键场景调用这两条指令。
2. 不可屏蔽中断(Non-Maskable Interrupt)
当不可屏蔽中断发生时,CPU会立即停止当前的执行流程,保存必要的上下文信息,然后跳转到预设的NMI处理程序去执行相应的处理代码。
即使在 CPU 执行 CLI 指令 禁止了可屏蔽中断 的情况下也不例外。
由于NMI的重要性,其处理过程一般要求快速、简洁,尽量减少对系统运行的影响。
- NMI触发的原因可能包括但不限于以下几种情况:
- 硬件故障:如电源故障、内存错误、严重硬件故障等;
- 系统调试需求:在调试环境中,开发者可能通过人工或硬件手段触发NMI,以便快速进入调试模式;
- 监控程序:某些嵌入式系统或服务器中,监控程序可能会通过NMI报告严重的系统错误或警告;
- 性能计数器溢出:某些高性能处理器中,性能监控单元(PMU)的计数器溢出可能导致NMI。
设计思想
可屏蔽中断:几乎都是外设触发的。告诉CPU来活了。
不可屏蔽中断:是发生了必须紧急处理的事件。CPU要先解决它了再说别的。
15.3 PC 机键盘的处理过程
1. 键盘输入
键盘上每个键分:按下、松开两种状态都会产生相应的扫描码。
按下时的叫通码,松开时的叫断码。
它会被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为 60h
断码 = 通码 + 80h
比如: g 键的通码为 22h,断码为 a2h。
表 15.1 是键盘上部分键的扫描码,只列出通码。

2. 引发 9 号中断
60h 端口收到信号,相关的芯片就会向 CPU 发出中断类型码为9的可屏蔽中断信息。
CPU 收到后,如果 IF=1,则响应中断,引发中断过程,转去执行 int 9 中断例程。
3. 执行 int 9 中断例程
BIOS 提供 int 9 中断例程,处理基本的键盘输入:
- 首先,中断例程通常会从60h端口读取扫描码。
- 处理扫描码
2.1. 若是字符键,则将扫描码转换为ASCII码,存入键盘缓冲区。 2.2. 若是功能键或控制键,则可能更新内存中的键盘状态字节`或其他内部状态。 - 向键盘控制器发送应答信号,表明中断已被处理。
BIOS键盘缓冲区:
BIOS键盘缓冲区是系统启动时BIOS设置的一块内存区域,用于存储15个键盘输入事件,每个事件占用2字节,其中高位字节为扫描码,低位字节为字符码。- 这个缓冲区通过
int 9中断机制收集并暂存键盘输入,确保在操作系统尚未完全加载或正忙时也能记录用户的按键动作。
| 字单元(1) | 字单元(2) | … | 字单元(15) |
|---|---|---|---|
| 高位-扫描码 | 高位-扫描码 | … | 高位-扫描码 |
| 高位-字符码 | 高位-字符码 | … | 高位-字符码 |
0040:17 单元存储键盘状态字节,该字节记录了控制键和切换键的状态。字节各位信息如下。
| 位 | 状态 |
|---|---|
| 0 | 右 Shift 状态,置1表示按下右 Shift 键: |
| 1 | 左 Shitt 状态,置1表示按下左 Shit 键; |
| 2 | Ctrl 状态,置1表示按下 Ctrl 键; |
| 3 | Alt 状态,置1表示按下 Alt 键; |
| 4 | ScrollLock状态,置1表示 Scroll 指示灯亮; |
| 5 | NumLock 状态,置1表示小键盘输入的是数字; |
| 6 | CapsLock 状态,置1表示输入大写字母: |
| 7 | Insert 状态,置1表示处于删除态。 |
15.4 编写int9 中断例程
键盘输入的处理过程:
- 键盘产生扫描码;
- 扫描码送入
60h端口; - 引发
9号中断; - CPU 执行
int 9中断例程处理键盘输入。
前三步都是硬件系统的活,我们能插手的就只有和4步。但因为 int 9 中断处理程序要与一些硬件细节打交到。所以我们只对 int 9 做下封装扩展。
编程
在屏幕中间依次显示“a”~“z”,并可以让人看清。在显示的过程中,按下 Esc 键后,改变显示的颜色。
思路
- 先循环显示
a ~ z。(为了看清,书上给的方案是空循环模拟延迟效果) - 自己写一个
int 9代替原版。
2.1. 我们自己的int 9中调用原版 int 9。
2.2. 拿到原版int 9返回的扫描码。
2.3. 判断如果是Esc修改显存改变颜色。
代码
assume cs:code
stack segmentdb 128 dup(0)
stack endsdata segmentoint9 dw 0,0
data endscode segmentstart: mov ax,stack ; 设置栈段和栈顶位置mov ss,axmov sp,128mov ax,data ; 设置数据段mov ds,axmov ax,0 ; 设置附加段mov es,ax; ------------ 保存原 int 9 中断列和入口到 ds:0, ds:2 ------------push es:[9*4]pop ds:[0]push es:[9*4+2]pop ds: [2]; ---------------- 将我们的新 int 9 写入中断向量表 ----------------mov word ptr es:[9*4],offset int9mov es:[9*4+2],cs; ------------------------- 显示 a 到 z -------------------------mov ax,0b800h ; 设置显存段mov es,axmov ah,'a' ; 要显示的字符串,从 a 开始s: mov es:[160*12+40*2],ah ; 显示字符call delay ; 调用子程序:延时inc ah ; 下一个字符cmp ah,'z' ; 如果不是z继续循环jna s; ------------- 将中断向量表中 int 9恢复为原来的地址 -------------mov ax,0mov es,axpush ds:[0]pop es:[9*4]push ds:[2]pop es:[9*4+2]mov ax,4c00hint 21h
; =======================================================
; --------------------- 子程序 delay -------------------
; 让CPU空循环,模拟延时效果
; -------------------------------------------------------
; 参数: 无
; 返回: 无
; -------------------------------------------------------
delay:push ax ; 备份寄存器push dxmov dx,2h ; 循环 2h 次,可以自己把握mov ax,0
delays: sub ax,1sbb dx,0 ; 10000000h 循环递减cmp ax,0 ; 直到 ax, dx 都为 0 才跳出循环jne delayscmp dx,0jne delayspop dx ; 还原寄存器pop axret ; 返回
; ---------------------- 子程序 delay -------------------
; =======================================================; =======================================================
; --------------------- 子程序 int 9 -------------------
; 调用原 int 9 获取扫描码,实现按 Esc 变色
; -------------------------------------------------------
; 参数: 无
; 返回: 无
; -------------------------------------------------------
int9:push ax ; 备份寄存器push dxpush esin al,60h ; 从60h端口读取数据pushfpushfpop bxand bh,11111100bpush bxpopfcall dword ptr ds:[0] ; 调用原来的 int 9 中断例程cmp al,1jne int9retmov ax,0b800hmov es,axinc byte ptr es:[160*12+40*2+1]int9ret:pop es ; 还原寄存器pop dxpop axiret ; 返回
; --------------------- 子程序 int 9 ------------------
; =======================================================
code ends
end start
检测点 15.1
《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 15.1
15.5 安装新的 int 9 中断例程
| 任务 | 安装一个新的 int9 中断例程。 |
|---|---|
| 功能 | 在 DOS下,按F1键后改变当前屏幕的显示颜色,其他的键照常处理 |
分析
- 改变屏幕的显示颜色。
改变从B8000H开始的4000个字节中的所有奇地址单元中的内容
mov ax,0b800hmov es axmov bx,1mov cx,2000
s: inc byte ptr es:[bx]add bx,2loop s
-
按键常规处理
直接调用原 int 9 -
原 int9 入口地址
不能保存在安装程序中。我们把它放在0:0200。 -
安装新 int9 中断例程
0:0200 ~ 0:0203用来保存原 int9 的地址了。
我们保存新 int9 时从0:0204开始。
代码
assume cs:code
stack segmentdb 128 dup(0)
stack endscode segmentstart: mov ax,stack ; 设置栈段和栈顶位置mov ss,axmov sp,128; -------- 安装: 复制中断例程到目标内存 -------mov ax,cs ;设置 ds:si 指向源地址mov ds,axmov si,offset int9mov ax,0 ;设置 es:di 指向目的地址mov es,axmov di,204h mov cx,offset int9end-offset int9 ;设置 cx为传输长度cld ;设置传输方向为正。movsb中si,di递增rep movsb ;重复复制数据次数由 cx 控制; -------- 安装: 复制中断例程到目标内存 -------; ---------- 备份原 int9 入口到 [0:200~0203] ----------push es:[9*4]pop es:[200h]push es:[9*4+2]pop es:[202h]; ---------- 备份原 int9 入口到 [0:200~0203] ----------; ---------- 设置中断向量表 ----------cli ; 临时屏蔽中断mov word ptr es:[9*4],204h ; 设置的偏移地址(0~3用来存原int9地址了)mov word ptr es:[9*4+2],0 ; 设置的段地址sti ; 恢复中断; ---------- 设置中断向量表 ----------ok: mov ax,4c00hint 21h; =======================================================
; --------------------- 子程序 int 9 -------------------
; 调用原 int 9 获取扫描码,实现按 Esc 变色
; -------------------------------------------------------
; 参数: 无
; 返回: 无
; -------------------------------------------------------
int9:push ax ; 备份寄存器push bxpush cxpush esin al,60h ; 从60h端口读取数据; 模拟 int 指令,用 call 调用原 int 9pushf ; 进入中断后 IF、TF已经是0 直接入栈即可call dword ptr cs:[200h] ; 调用原来的 int 9 中断例程cmp al,3bh ; 判断是否 F1 键jne int9ret ; 如果不是直接结束mov ax,0b800h ; 设置显存mov es,axmov bx,1mov cx,2000s: inc byte ptr es:[bx]add bx,2loop sint9ret:pop es ; 还原寄存器pop cxpop bxpop axiret ; 返回
int9end:nop; --------------------- 子程序 int 9 ------------------
; =======================================================
code ends
end start
运行效果

实验 15 安装新的 int9 中断例程
《汇编语言》- 读书笔记 - 第15章-外中断-实验15 安装新的 int9 中断例程
相关文章:
《汇编语言》- 读书笔记 - 第15章-外中断
《汇编语言》- 读书笔记 - 第15章-外中断 15.1 接口芯片和端口15.2 外中断信息1. 可屏蔽中断(Maskable Interrupt)2. 不可屏蔽中断(Non-Maskable Interrupt)设计思想 15.3 PC 机键盘的处理过程1. 键盘输入2. 引发 9 号中断3. 执行…...
【Vue3】CSS 新特性
:slotted <template> <!-- App.vue--><Son ><div class"a">我要插入了</div></Son> </template><script setup lang"ts"> import Son from ./components/Son.vue </script><style></sty…...
四信水电站泄洪预警方案,精准提升防汛应急水平
2022年5月水利部办公厅发布《关于开展水库泄洪设施专项排查整改的紧急通知》,为坚决贯彻落实关于水库大坝安全的重要指示批示精神、关于保障水库泄洪通道通畅的批示要求,全力防范水库可能出现的重大险情,确保水库安全度汛。 2023年3月国家能源…...
k8s中容器的调度与创建:CRI,cgroup
container调度与创建 选自:K8s、CRI与container - packy的文章 - 知乎 https://zhuanlan.zhihu.com/p/102897620 Cgroup创建: cgexec -g cpu,memory:$UUID \ > unshare -uinpUrf --mount-proc \ > sh -c "/bin/hostname $UUID &…...
Unity安装与简单设置
安装网址:https://unity.cn 设置语言: 设置安装位置:否则C盘就会爆了 获取一个个人的资格证: 开始安装: 安装完毕。 添加模块:例如简体中文 新建项目: 布局2*3、单栏布局、 设置…...
数据库的介绍、分类、作用和特点
数据库是用来存储、管理和检索数据的集合系统。根据数据处理模型的不同,数据库可以分为多种类型,主要包括: 1、关系型数据库(RDBMS): 介绍:关系型数据库使用表格形式来存储数据,并通…...
【Unity】机器人末端执行器仿真
机械手臂的末端执行器使用多项式来计算转动角度可能有几个原因: 精确控制:机械臂的运动通常需要高度的精确性,特别是在精密工作或复杂运动轨迹的情况下。多项式,特别是高阶的,可以很好地近似复杂的非线性关系和运动轨迹…...
更换个人开发环境后,pycharm连接服务器报错Authentication failed
原因:服务器中更换个人开发环境后,密码变了。 解决:在pycharm中修改服务器开发环境密码即可。 1 找到Tools-Depolyment-Configuration 2 点击SSH Configuration后的省略号 3 修改这里面的Password即可...
E - Bad Juice
解题思路 由于最后返回一个01字符串表示所选人的状态要求人数最少,即字符串长度最少而要用最少的字符,找出则返回的字符为二进制下的编号这样利用了所有的01字符号人表示二进制下位的情况注意对于2的次方项,只需要有位,可以用位均…...
用HTML5的<canvas>元素实现刮刮乐游戏
用HTML5的<canvas>元素实现刮刮乐游戏 用HTML5的<canvas>元素实现刮刮乐,要求:将上面的“图层”的图像可用鼠标刮去,露出下面的“图层”的图像。 示例从简单到复杂。 简单示例 准备两张图像,我这…...
TypeScript + react 中 TypeScript 的加入后 , 有哪些优化项目
在使用 TypeScript 结合 React 进行开发时,TypeScript 提供了许多优化和增强代码质量的方式。以下是一些关键的优化操作和最佳实践: 强类型组件属性(Props)和状态(State): 使用接口或类型别名定义组件的 pr…...
Redis学习路径(构建体系)
学习路径 掌握数据类型(分析底层数据结构)和缓存的基本使用 (理论使用) 掌握 redis 实现高性能,高可靠、高可用技术 (理论)学习redis源代码底层实现 (底层实现) 先来一个引言,比较宏观的角度…...
【README 小技巧】 展示gitee中开源项目start
【README 小技巧】 展示gitee中开源项目start <a target"_blank" hrefhttps://gitee.com/wujiawei1207537021/wu-framework-parent><img srchttps://gitee.com/wujiawei1207537021/wu-framework-parent/badge/star.svg altGitee star/></a>...
tcping实用小工具
Tcping实用小工具命令详解 一、tcping介绍 tcping:tcping命令基于tcp协议监控,可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从容硬线连接到分组交换或电路交换网络的各种通信系统之上操作。 …...
【Web】Java反序列化之CC2——commons-collections4的新链之一
目录 关于commons-collections4 一个重要的思维模型 触发Transform的关键类:TransformingComparator 反序列化的入口:PriorityQueue Exp 关于commons-collections4 commons-collections4 是 Apache Commons 组件库中的一个项目,它是对旧…...
golang使用gorm操作mysql1
1.mysql连接配置 package daoimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger" )var DB *gorm.DB// 连接数据库,启动服务的时候,init方法就会执行 func init() {username : "roo…...
Flutter异常上报及性能监控实现
1. 页面异常监测 在Flutter中,通常用FlutterError监测Flutter框架抛出的异常,用runZonedGuarded监测应用中用户代码异常。 class AppGuarded {run(Widget app) {//1. 用FlutterError监测flutter框架抛出的异常FlutterError.onError (FlutterErrorDetail…...
基于springboot+vue的工厂车间管理系统
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 主要内容:毕业设计(Javaweb项目|小程序|Pyt…...
Java基础 - Stream 流:Stream API的终端操作
在前两篇博客中,我介绍了构建 Stream 流的多种方式,以及 Stream API 的中间操作,如果你还没有阅读,你可以点击这里和这里查看。 Java基础 - Stream 流:构建流的多种方式 Java基础 - Stream 流:Stream API…...
高级语言期末2009级A卷(计算机学院)
1.编写函数,打印下列序列0,1,1,2,3,5,8,13,21,34...(斐波那契序列)的前n项 #include <stdio.h>int main() {int x0,y1,z,n;scanf("%d",&…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
高分辨率图像合成归一化流扩展
大家读完觉得有帮助记得关注和点赞!!! 1 摘要 我们提出了STARFlow,一种基于归一化流的可扩展生成模型,它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流(TARFlow&am…...
