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

推荐订阅源

博客园 - 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-01-30 · via faryou的博客

前言

中断是CPU中用于处理其内外突发情况的一种机制。CPU执行完当前的指令后,检测到CPU内部或外部传送的一种特殊信息(称“中断信息”),立刻处理这些信息,处理方式即立刻跳转到中断的对应处理程序,执行完这段程序后再返回。中断机制常在CPU及操作系统提供磁盘操作、键盘输入、屏幕输出等处理程序时使用,可以视为早期16位操作系统的一种“API”,本质是一种具有特殊触发条件的函数。下面我们将详细学习几种种情况引起的中断,以及编写程序时如何利用中断机制。

中断的过程

当8086CPU收到中断信息后,处理过程如下:

(1)取得中断类型码
(2)pushf
(3)修改TF、IF值为0
(4)CS、IP入栈
(5)进入中断程序(通过修改CS、IP的值)
(6)恢复CS、IP、标志寄存器的值(从而返回程序)

需要注意的是,如果进入中断的前一条指令修改了ss寄存器的值,那么即使触发了中断条件,也不会进入中断程序。因为ss:sp是一个整体,若ss:sp值不对应则会引起中断之后的错误,所以CPU提供了这一特性。

中断向量表

8086CPU支持256个中断,为此,规定内存0000:0000~0000:03FF的1024个单元存放0~255号中断的入口,从而建立中断类型码(即中断的编号)与中断程序之间的一一映射关系。其中,每两个字存放一个中断处理程序的地址,高位存放中断处理程序的偏移地址,低位存放其段地址。由此,不难理解,当CPU获得中断类型码N后,即通过设置CS:IP的值为(N4):(N4+2)跳转到中断处理程序,中断结束后再返回原来的位置。

内中断

内中断的中断信息由CPU内部产生。对8086CPU,当发生如下四种情况时,会引起内中断:

(1)除法错误(执行div等除法指令时,除数为0)
(2)单步执行(使用debug的时候)
(3)执行into指令
(4)执行int指令

下面将分别介绍说明~

除法错误中断

除法错误中断为0号中断,用于处理div等除法指令除数为零的错误。让我们执行下面的程序:

mov ah,0
mov bh,1
div bh

可以看到,屏幕上输出了“Divide overflow!”,但我们并没有写输出字符串的程序。原因是:这里出现了除数为0的错误,从而引发0号中断,0号中断处理程序的功能即输出字符串“Divide overflow”。

单步中断

单步中断为1号中断,用于提供Debug的单步执行功能。在使用Debug调试时,我们经常需要逐条调试代码(即使用T命令),单步中断就是提供这一功能的中断。其触发条件为TF值为1。这样我们就很容易理解为什么进入中断之前要设置TF值为0了:如果进入中断前TF值为1,那么执行中断处理程序的第一条指令后,CPU检测到TF值为1,触发单步中断,进入其中断处理程序;执行完中断处理程序之后,又检测到TF值为1,又重新执行1号中断的第一条指令;陷入死循环。

into指令引发内中断

into指令检测上一条计算指令是否发生了溢出,若是,则进入4号中断。我们可以通过修改4号中断对应的程序,实现需要的功能(后面会详细介绍)。into指令的格式:

into

int指令引发内中断

int指令的功能是引发中断过程,我们前面所说的中断承载的“API”功能即主要通过int指令实现。其使用格式:

int 中断类型码

操作系统把“API”以中断形式写到内存里,应用程序通过int指令即可方便地调用。同时,int指令也可以用于不同程序间的数据互通,这对于早期的单任务操作系统尤为重要。我们之前写程序最后总有一句:

int 21h

中断类型码21H对应的中断功能即为:返回操作系统。这为应用程序提供了快速返回操作系统的方式。
接下来我们学习如何自己利用中断机制~

自己编写中断程序

我们来实现一个40h中断,包括如下功能:

(0)清理屏幕
(1)显示日期
(2)显示时间

按照汇编的惯例,一个中断里常有多个功能,在调用其中一个子功能时,一般用ah寄存器传递功能号。我们之前的程序中:

mov ax,4c00h

就是传递21h中断的参数。接下来考虑我们这个中断处理程序的实现有哪些步骤。很显然,我们需要如下的步骤:

(1)用到的寄存器入栈保存
(2)中断处理程序
(3)寄存器出栈
(4)返回

中断返回一般用iret指令,其功能相当于:

pop IP
pop CS
popf

中断程序也占用空间。我们这里只是进行练习,所以只要别让代码影响到操作系统即可。所以我们直接扔到闲置的中断向量表区,即0000:0200~0000:03FF区域。
下面开始编写~

assume cs:codesg

;安装程序
codesg segment
setup:
  mov ax,cs
  mov ds,ax
  mov si,offset code
  mov ax,0
  mov es,ax
  mov di,200h

  mov cx,offset codeend-offset code
  cld
  rep movsb

  mov ax,0
  mov ds,ax
  mov word ptr [4*40h],200h
  mov word ptr [4*40h+2],0

  mov ax,4c00h
  int 21h

;中断处理程序
code:
  cmp ah,2
  jae codeback
  mov bx,ax
  shl bx
  jmp word ptr codetable[bx]
run0:
  push cx
  mov cx,4000
  push ax
  push ds
  mov ax,0b800h
  mov ds,ax
  rep mov byte ptr [cx],0
  pop ds
  pop ax
  pop cx
run1:
  push cx
  mov cx,3
  push ax
  push bx
  push dx
  mov ax,cs
  mov ds,ax
  mov ax,0b800h
  mov es,ax
  mov bx,14
run1_loop:
  mov al,codedata1[cx]
  out al,70h
  in 71h,al
  mov ah,al
  shr ah,4
  and al,00001111b
  add al,30h
  add ah,30h
  mov byte ptr es:[bx],al
  sub bx,2
  mov byte ptr es:[bx],ah
  sub bx,4
  loop run1_loop
  mov byte ptr es:[4],'/'
  mov byte ptr es:[10],'/'
  pop dx
  pop bx
  pop ax
  pop cx
  iret
run2:
  push cx
  mov cx,3
  push ax
  push bx
  push dx
  mov ax,cs
  mov ds,ax
  mov ax,0b800h
  mov es,ax
  mov bx,14
run2_loop:
  mov al,codedata2[cx]
  out al,70h
  in 71h,al
  mov ah,al
  shr ah,4
  and al,00001111b
  add al,30h
  add ah,30h
  mov byte ptr es:[bx],al
  sub bx,2
  mov byte ptr es:[bx],ah
  sub bx,4
  loop run2_loop
  mov byte ptr es:[4],':'
  mov byte ptr es:[10],':'
  pop dx
  pop bx
  pop ax
  pop cx
  iret
codeback:iret
codetable dw run0,run1,run2
codedata1 db 9,8,7
codedata2 db 4,2,0
codeend:nop
codesg ends
end setup

执行过上述程序之后,40h号中断即安装进了系统,我们执行下面的指令即可调用:

mov ah,1;这里以1号功能为例,会显示日期
int 40h

外中断

外中断是用于外部硬件引发的中断,通常用来处理硬件相关的信息。外部设备全部通过端口接入PC机,而外中断就是在某些端口的信息送达CPU时引发的中断。下面我们来了解外中断。
首先,外接设备多种多样,而主板本身并没有这么多的端口来接入各种外部设备。况且对于外中断,在一般情况下都应该立刻作出反应。因此,我们需要一个中介,连接主板与外部设备,并向CPU发送外接设备的中断类型码。这个设备就是中断控制芯片。我们以8259A中断控制芯片为例(因为它是8086机上最常见的)。8259A上有8个端口,以接入8种不同的设备。当外部中断(如键盘输入)发生时,它通过预先设定好的外部中断-中断类型码映射关系,找到键盘中断对应的信息,并传递给CPU。然后,CPU执行中断处理程序。
BIOS中的9号中断有基本的键盘处理程序,以进行基本的输入输出处理,包括:

(1)读入扫描码
(2)如果该扫描码代表字符键,刚将该扫描码与对应的ASCLL码送入BIOS键盘缓冲区(该缓冲区由16h号中断管理);如扫描码代表控制键或切换键,则将其转变为状态字节,写入内存的0040:0017单元。
(3)完成对硬件系统的应答

其中最后一步是普遍适用于所有外中断的。它向8259A发送中断处理完毕的信息,从而继续工作。其实现如下:

mov al,0x20
out 0x20,al
out 0xa0,al
iret

这段代码向8259A发送EOI信息,以使其继续工作。
之后的内容我们会进一步学习各种硬件中断的具体实现,这里只作基本了解~