汇编语言输入输出的中断.docx
《汇编语言输入输出的中断.docx》由会员分享,可在线阅读,更多相关《汇编语言输入输出的中断.docx(38页珍藏版)》请在冰豆网上搜索。
![汇编语言输入输出的中断.docx](https://file1.bdocx.com/fileroot1/2023-1/21/757f763a-b3e9-4f16-9732-a630ca0210d2/757f763a-b3e9-4f16-9732-a630ca0210d21.gif)
汇编语言输入输出的中断
第8章输入输出和中断
输入输出功能是计算机的重要组成部分,是人—机交互功能的主要承担者。
在早期的计算机系统中,通常把输入输出设备或功能作为次要的部分,而把CPU作为主要研究对象。
但现在随着输入输出设备的日益丰富、功能要求越来越复杂,输入输出部分在整个计算机系统中的地位也得到了进一步提高。
本章先介绍了I/O的基本概念和I/O指令,再叙述了中断的概念及其工作过程,并列举出计算机系统中若干个常用的中断及其功能。
8.1输入输出的基本概念
输入输出是一个完整应用程序的重要组成部分,是交互式应用程序不可缺少的组成部分。
在用高级语言编程时,程序员可直接用输入输出语句来完成键盘输入、屏幕显示或打印输出等需求,而无需关心这些输入输出语句是如何实现的,因为编译程序会自动把这些语句转换成相应的输入输出指令。
但如果用汇编语言编写程序的话,情况就不同了,因为汇编语言是与机器有关的程序设计语言,要编写出具有输入输出功能的代码段就必须清楚CPU为输入输出提供了哪些指令,或计算机系统提供了哪些可直接使用的功能调用。
8.1.1I/O端口地址
I/O端口是CPU与输入输出设备的交换数据的场所,通过I/O端口,处理机可以接受从输入设备输入的信息;也可向输出设备发送信息。
在计算机系统中,为了区分各类不同的I/O端口,就用不同的数字给它们进行编号,这种对I/O端口的编号就称为I/O端口地址。
按照
每次可交换一个字节数据的端口称为字节端口,每次可交换一个字数据的端口称为字端口。
在Intel公司的CPU家族中,I/O端口的地址空间可达64K,即可有65536个字节端口,或32768个字端口。
这些地址不是内存单元地址的一部分,不能普通的访问内存指令来读取其信息,而要用专门的I/O指令才能访问它们。
虽然CPU提供了很大的I/O地址空间,但目前大多数微机所用的端口地址都在0~3FFH范围之内,其所用的I/O地址空间只占整个I/O地址空间的很小部分。
表8.1列举了几个重要的I/O端口地址。
表8.1几个重要的I/O端口地址
端口地址
端口名称
端口地址
端口名称
020H~023H
中断屏蔽寄存器
378H~37FH
并行口LPT2
040H~043H
时针/计数器
3B0H~3BBH
单色显示器端口
060H
键盘输入端口
3BCH~3BFH
并行口LPT1
061H
扬声器(0,1位)
3C0H~3CFH
VGA/EGA
200H~20FH
游戏控制口
3D0H~3DFH
CGA
278H~27FH
并行口LPT3
3F0H~3F7H
磁盘控制器
2F8H~2FFH
串行口COM2
3F8H~3FFH
串行口COM1
计算机在启动时,BIOS程序(BasicInput/OutputSystem)将检查计算机系统中有哪些端口地址。
当发现有串行端口地址时,BIOS就把该端口存放在以地址40:
00H开始的数据区内;当发现有并行端口地址时,BIOS会把它存入以地址40:
08H开始的数据区内。
每类端口有4个字的空间,对有二个串行口、二个并行口的计算机系统,其BIOS程序将得到如图8.1所示的部分数据表。
图中03F8H、02F8H、0378H和0278H分别为COM1、COM2、LPT1和LPT2的端口地址。
8.1.2I/O指令
由于I/O端口地址和内存单元地址是相互独立的,这些端口地址不能普通的访问内存指令来访问其信息,所以,在CPU的指令系统中就专门设置了I/O指令来存取I/O端口的信息。
按功能分类来看,I/O指令应属于数据传送指令。
1、输入指令IN
输入指令IN的一般格式如下:
IN AL/AX,PortNo/DX
该指令的作用是从端口中读入一个字节或字,并保存在寄存器AL或AX中。
如果某输入设备的端口地址在0~255范围之内,那么,可在指令IN中直接给出,否则,要把该端口地址先存入寄存器DX中,然后在指令中由DX来给出其端口地址。
例如:
IN
AL,60H
;从端口60H读入一个字节到AL中
IN
AX,20H
;把端口20H、21H按“高高低低”组成的字读入AX
MOV
DX,2F8H
IN
AL,DX
;从端口2F8H读入一个字节到AL中
IN
AX,DX
;把端口2F8H、2F9H按“高高低低”组成的字读入AX
2、输出指令OUT
输出指令OUT的一般格式如下:
OUT PortNo/DX,AL/AX
该指令的作用是把寄存器AL或AX的内容输出到指定端口。
如果某输出设备的端口地址在0~255范围之内,那么,可在指令OUT中直接给出,否则,要把该端口地址先存入寄存器DX中,然后在指令中由DX来给出其端口地址。
例如:
OUT
61H,AL
;把AL的内容输出到端口61H中
OUT
20H,AX
;把AX的内容输出到端口20H、21H中
MOV
DX,3C0H
OUT
DX,AL
;把AL的内容输出到端口3C0H中
OUT
DX,AX
;把AX的内容输出到端口3C0H、3C1H中
有关字符串的输入输出指令,请见5.2.11节中的介绍。
8.2中断
在计算机系统中,引入中断的最初目的是为了提高系统的输入输出性能。
随着计算机应用的发展,中断技术也应用到计算机系统的许多领域,如:
多道程序、分时系统、实时处理、程序监视和跟踪等领域。
8.2.1中断的基本概念
下面只简单介绍与汇编语言程序设计有关的中断知识,使本章的知识具有一定完整性。
有关中断的详细介绍可参阅《计算机组成原理》课程中的相关章节。
1、中断和中断源
所谓中断就是CPU暂停当前程序的执行,转而执行处理紧急事务的程序,并在该事务处理完后能自动恢复执行原先程序的过程。
在此,称引起紧急事务的事件为中断源,称处理紧急事务的程序为中断服务程序或中断处理程序。
计算机系统还根据紧急事务的紧急程度,把中断分为不同的优先级,并规定:
高优先级的中断能暂停低优先级的中断服务程序的执行。
计算机系统有上百种可以发出中断请求的中断源,但最常见的中断源是:
外设的输入输出请求,如:
键盘输入引起的中断,通信端口接受信息引起的中断等;还有一些计算机内部的异常事件,如:
0作除数、奇偶校验错等。
CPU在执行程序时,是否响应中断要取决于以下三个条件能否同时满足:
(1)、有中断请求;
(2)、允许CPU接受中断请求;
(3)、一条指令执行完,下一条指令还没有开始执行。
条件
(1)是响应中断的主体。
除用指令INT所引起的软件中断之外,其它中断请求信号是随机产生的,程序员是无法预见的。
程序员可用程序部分地控制条件
(2)是否满足,即可用指令STI和CLI来允许或不允许CPU响应可屏蔽的外部中断。
而对于不可屏蔽中断和内部中断,CPU一定会响应它们的,程序员是无控制权的。
CPU一定会执行这些中断的中断服务程序。
2、断向量表和中断服务程序
中断向量表是一个特殊的线性表,它保存着系统所有中断服务程序的入口地址(偏移量和段地址)。
在微机系统中,该向量表有256个元素(0~0FFH),每个元素占4个字节,总共1K字节,其在内存中的存储形式及其存储内容如图8.2所示。
图8.2中的“中断偏移量”和“中断段地址”是指该中断服务程序入口单元的“偏移量”和“段地址”。
由此不难看出:
假如中断号为n,那么,在中断向量表中存储该中断处理程序的入口地址的单元地址为:
4n。
表8.2说明了前16个中断向量表中列举了部分常用的中断号。
图8.2中断向量表
表8.2部分常用的中断号及其含义
中断号
含义
中断号
含义
0
除法出错
8
定时器
1
单步
9
键盘
2
非屏蔽中断
A
未用
3
断点
B
COM2
4
溢出
C
COM1
5
打印屏幕
D
硬盘(并行口)
6
未用
E
软盘
7
未用
F
打印机
8.2.2引起中断的指令
中断处理程序基本上是系统程序员编写好的,是为操作系统或用户程序服务的。
为了在应用程序中使用中断服务程序,程序员必须能够在程序中有目的地安排中断的发生。
为此,指令系统提供了各种引起中断的指令。
1、中断指令INT
中断指令INT的一般格式如下:
INTImm
其中:
立即数Imm是一个0~0FFH范围内的整数。
指令执行的步骤:
◆、把标志寄存器压栈,清除标志位IF和TF;
◆、把代码段寄存器CS的内容压栈,并把中断服务程序入口地址的高字部分送CS;
◆、32位段,压32位IP。
在该指令执行完后,CPU将转去执行中断服务程序。
由于有了指令INT,程序员就能为满足某种特殊的需要,在程序中有目的地安排中断的发生,也就是说,该中断不是随机产生的,而是完全受程序控制的。
一般情况下,一个中断可有很多不同的功能,每个功能都有一个唯一的功能号,所以,在安排中断之前,程序员还要决定需要该中断的哪个功能,中断的功能号都是由AH来确定的。
有些中断还需要其它参数,常用中断的功能和参数如附录3所列。
2、溢出指令INTO
当标志位OF为1时,引起中断。
该指令的格式如下:
INTO
该指令影响标志位:
IF和TF。
8.2.3中断返回指令
当一个中断服务程序执行完毕时,CPU将恢复被中断的现场,返回到引起中断的程序中。
为了实现此项功能,指令系统提供了一条专用的中断返回指令。
该指令的格式如下:
IRET/IRETD
该指令执行的过程基本上是INT指令的逆过程,具体如下:
◆、从栈顶弹出内容送入IP;
◆、再从新栈顶弹出内容送入CS;
◆、再从新栈顶弹出内容送入标志寄存器;
对80386及其以后的CPU,指令IRETD从栈顶弹出32位内容送入EIP。
8.2.4中断和子程序的比较
中断和子程序调用之间有其相似和不同之处。
它们的工作过程非常相似,即:
暂停当前程序的执行,转而执行另一程序段,当该程序段执行完时,CPU都自动恢复原程序的执行。
如图8.3所示。
图8.3中断和子程序调用的工作过程
它们的主要差异有:
◆、
子程序调用一定是程序员在编写源程序时事先安排好的,是可知的,而中断是由中断源根据自身的需要产生的,是不可预见的(用指令INT引起的中断除外);
◆、
子程序调用是用CALL指令来实现的,但没有调用中断的指令,只有发出中断请求的事件(指令INT是发出内部中断信号,而不要理解为调用中断服务程序);
◆、
子程序的返回指令是RET,而中断服务程序的返回指令是IRET/IRETD。
◆、
在通常情况下,子程序是由应用系统的开发者编写的,而中断服务程序是由系统软件设计者编写的。
8.3.中断功能的分类
计算机系统有上百种中断,若按中断的性质来划分,则系统中的中断可分为:
可屏蔽中断和不可屏蔽中断。
对不可屏蔽中断,程序员不能控制它,系统肯定会立即响应的,而对于可屏蔽中断,汇编语言程序员可以通过指令CLI和STI来控制对它们的响应。
若按中断源来划分,则系统中的中断又可分为:
硬件中断和软件中断。
对于硬件中断,程序员不能控制它,它们基本上是随机产生的,而对于软件中断,汇编语言程序员可通过指令INT和INTO来有目的安排它们的。
下面主要介绍汇编语言程序员能控制的软件中断的功能及其使用方法,常用的这类中断有:
DOS功能调用(INT21H)、BIOS中断、硬件和外设的中断等。
图8.4给出了程序员可使用的各类中断之间的层次关系。
图8.4各类系统中断之间的层次关系
在用户程序中,若直接通过端口来操作硬件或外设,那么,其处理过程没有额外的多余工作,处理速度显然是最快的,但这样做,无疑使用户程序具有了很大的局限性。
硬件环境的改变将直接影响程序的正常运行。
若用户程序通过调用DOS功能来实现其所需功能,那么,应用程序与低层硬件相距较远,操作最终的对象需要经过中间环节,处理速度肯定受到一定的损失,但这种应用程序适应性强,应用范围广,对硬件的依赖性最小。
由于BIOS介于DOS和具体硬件之间,所以,调用BIOS的功能是一个很好的折中方案。
程序员可在以下三种情况下考虑使用BIOS的功能:
1)、BIOS提供的功能,而DOS没有提供该功能的情况;
2)、不能利用DOS功能调用的情况(可能因为某些具体应用的限制);
3)、基于处理速度的考虑,需要绕过DOS层的情况。
综上所述,可以归纳出如下结论:
使用中断的层次越高,它与硬件设备相关程度就越低,处理速度也就越低,但用户程序的适用范围较广。
反之也然。
有了上面的结论,程序员可根据应用程序的要求、对硬件环境的熟悉程度等因素来选用不同层次的中断。
8.3.1键盘输入的中断功能
键盘输入是绝大多数程序的主要输入方式,学习和掌握有关键盘输入中断的使用方法对编写交互式程序是非常重要的,也能更进一步理解计算机是如何接受键盘输入的。
1、键盘缓冲区
键盘缓冲区是一个先进先出的环形队列,其所占内存区域如下:
KBHead
DW ?
;其内存地址为0000:
041AH,缓冲区头指针
KBTail
DW ?
;其内存地址为0000:
041CH,缓冲区尾指针
KBBuff
DW 16DUP(?
)
;其内存地址为0000:
041EH,该缓冲区的缺省长度为16个字
与键盘有关的其它地址请见附录6之键盘地址。
键盘缓冲区是一个环形队列,其性质与《数据结构》课程中对“环形队列”所描述的性质完全一致。
虽然缓冲区的本身长度为16个字,但出于判断“对列满”的考虑,它最多只能保存15个键盘信息。
当缓冲区满时,系统将不再接受按键信息,而会发出“嘟”的声音,以示要暂缓按键。
当KBHead=KBTail时,表示无键盘输入。
2、键盘状态字
在计算机键盘上除了可输入各种字符(字母、数字和符号等)的按键之外,还有一些功能键(如:
F1、F2、…等)、控制键(如:
Ctrl、Alt、Shift等)、双态键(如:
NumLock、CapsLock等)和特殊请求键(如:
PrintScreen、ScrollLock等)。
键盘中的控制键和双态键是非打印按键,它们是起控制或转换作用的。
当使用者按下控制键或双态键时,系统要记住其所按下的按键。
为此,在计算机系统中,特意安排的一个字来标志这些按键的状态,我们称该字为键盘状态字。
键盘状态字的各位含义如图8.5所示。
图8.5键盘状态字的各位含义
3、键盘中断的处理过程
当用户按键时,键盘接口会得到一个代表该按键的键盘扫描码,同时产生一个中断请求。
键盘中断服务程序先从键盘接口取得按键的扫描码,然后根据其扫描码判断用户所按的键并作相应的处理,最后通知中断控制器本次中断结束并实现中断返回。
若用户按下双态键(如:
CapsLock、NumLock和ScrollLock等),则在键盘上相应LED指示灯的状态将发生改变;
若用户按下控制键(如:
Ctrl、Alt和Shift等),则在键盘标志字中设置其标志位;
若用户按下功能键(如:
F1、F2、…等),再根据当前是否又按下控制键来确定其系统扫描码,并把其系统扫描码和一个值为0的字节存入键盘缓冲区;
若用户按下字符键(如:
A、1、+、…等),此时,再根据当前是否又按下控制键来确定其系统扫描码,并得到该按键所对应的ASCII码,然后把其系统扫描码和ASCII码一起存入键盘缓冲区;
若用户按下功能请求键(如:
PrintScreen等),则系统直接产生一个具体的动作。
有关键盘中各种单键、组合键的扫描码及其相应的ASCII码,请参阅本书的附录5。
4、DOS功能中的键盘输入
键盘输入是一种最常用的输入方式,所以,在DOS操作系统中,提供了能实现各种键盘输入的功能(Windows操作系统中仍然能用)。
INT21H中的相关功能如下:
01H——带回显的键盘输入
06H——控制台的输入/输出:
当DL=0FFH,表示键盘输入
07H——不回显、不过滤的键盘输入
08H——不回显的键盘输入
0AH——键盘输入字符串
0BH——检查键盘输入状态
0CH——清除输入缓冲区的输入功能
有关中断功能的详细描述和调用参数在此从略,需要查阅者可参阅附录3之字符功能调用类。
5、BIOS中的键盘输入
在BIOS系统中,提供了中断16H来实现键盘输入功能。
其具体的功能如下:
00H、10H——从键盘读一个字符,输入字符不回显
01H、11H——判断键盘缓冲区内是否有字符可读
02H——读取当前键盘状态字
有关中断功能的详细描述和调用参数在此从略,需要查阅者可参阅附录3之键盘服务。
6、直接操作端口的键盘输入
由表8.1可知:
键盘输入端口的地址为60H,所以,我们可以用指令IN从该端口读取当前按键的扫描码。
例如:
MOV DX,60H
IN AL,DX
7、键盘输入的举例
例8.1用键盘最多输入10个字符,并存入内存变量Buff中,若按“Enter”键,则表示输入结束。
解:
1、方法1
.MODELSMALL
CR EQU 0DH
;定义“回车”键的符号名
.DATA
Buff DB 10DUP(?
)
.CODE
.STARTUP
MOV CX,0AH
LEA BX,Buff
.REPEAT
MOV AH,0H
INT 16H
;用BIOS中的中断功能
.BREAK .IF AL==CR
MOV [BX],AL
INC BX
.UNTILCXZ
.EXIT 0
END
2、方法2
.MODEL SMALL
.DATA
Buff DB 10,?
10DUP(?
)
;注意缓冲区的定义方式
.CODE
.STARTUP
LEA DX,Buff
MOV AH,0AH
INT 21H
;用DOS中的功能调用
.EXIT 0
END
8.3.2屏幕显示的中断功能
显示器是一个重要的输出设备,它通过显示卡与计算机系统相连。
显示器的显示屏通常称之为屏幕,现在常用的显示器有14"和17",常用的显示分辨率为800×600或1024×768等。
常用的显示卡类型为VGA、SVGA、EVGA和TVGA等,显示卡上也都带有大量的显示存储器,能快速显示精美的图象。
1、显示模式
计算机系统中的显示器都有二种显示方式:
文本显示方式和图形显示方式。
在DOS操作系统环境下,其默认的显示方式为文本显示方式,而在Windows操作系统环境下,其显示方式是图形显示方式,其绝大多数操作界面是以图形界面的窗口形式出现的。
可用的显示模式,请参阅附录3中的中断10H之功能00H中所列。
1)、文本显示方式
文本显示方式是指以字符为最小单位的显示方式,每个字符都是以矩形块形式显示的。
在BIOSROM中存有多种不同大小的字符集,主要的显示字符集大小为:
8×8(标准)、8×14和8×16等。
在常用的文本显示模式(模式3)下,屏幕被划分成25行,每行可显示80个字符,所以,每屏最多可显示2000(80×25)个字符。
为了便于标识屏幕上的每个显示位置,我们就用其所在行和列来表示之,并规定:
屏幕的左上角坐标为(0,0),右下角坐标为(24,79)。
在显示字符时,用一个字节存储该字符的ASCII码,用另一个字节存储的显示属性,即:
显示颜色。
彩色显示器的字符显示属性定义如图8.6所示,有关颜色值的定义,请参阅附录6中的表4。
图8.6字符显示属性的定义
存储内容与显示位置的对应关系如图8.7所示。
图8.7存储内容与显示位置的对应关系示意图
由上面的叙述可知:
在80×25的文本显示模式下,满屏可显示2000个字符,也就需要4000个字节来存储一屏的显示信息。
2)、图形显示方式
图形显示是目前最常用的一种显示方式,也是Windows操作系统的默认显示方式。
在该显示方式下,我们可以看到优美的图象、VCD、浏览丰富多彩的网页等。
图形显示的最小单位是象素,对每个象素可用不同的颜色来显示。
所以,在显示缓冲区内记录的信息是屏幕各象素的显示颜色。
由于各种图形显示模式所能显示的颜色和象素是不同的,它决定了显示缓冲区的存储方式也是不同的。
下面给出三个具体的图形显示模式及其存储方式,通过它们可看出各种显示模式在显示缓冲区存储方式上的明显差异。
(1)、4色320×200图形显示模式
由于每个象素只能是四种颜色之一,而四种情况用2位二进制就可表示,所以,一个字节可表示4个象素的显示颜色,存储一行上的所有象素信息就需要80个字节。
在具体存储过程中,它又把偶数行象素和齐数行分开来存储。
偶数行和齐数行的象素总数各有32000个,也都需要8000个字节来存储,并规定:
偶数行象素从0B800:
0000H开始存储,齐数行象素从0B800:
2000H开始存储。
该显示模式的存储形式如图8.8所示。
图8.8显示缓冲区存储方式示意图
(2)、16色640×480图形显示模式
640×480图形显示模式共有307200个象素,每个象素可选用16种颜色,它需要用4位二进制来表示。
该显示模式在存储显示信息时,把该4位分在四个位平面P1、P2、P3和P4上,所以,位平面Pi(i=1,2,3,4)共有307200个二进制位,即有38400个字节。
其显示缓冲区的存储形式如图8.9所示。
图8.9显示缓冲区存储方式示意图
由图8.9可看出:
若要改变某个象素的显示颜色,则需要在每个位平面上修改其对应的二进制位。
所以,若用操作显示缓冲区的方法来改变象素的颜色,那么编程将困难得多。
在屏幕上显示一个点,必须遵循以下步骤:
读入要改变的内存单元,把位平面信息装入显示卡;
通过图形地址寄存器(GAR)和位屏蔽寄存器(BMR)选择并寻址到其二进制位;
寻址并设定映像屏蔽寄存器(MMR)为0FH,在对应象素地址填入0(黑色)来清除象素的原有颜色;
通过MMR设定该象素当前所要颜色;
通过修改包含显示信息的内存单元来写象素。
对于该显示模式下,改变象素方法的详细描述和例子,请参阅参考书籍[2]、[4],或其它有关技术资料,在此不再进一步展开叙述。
若用BIOS中断10H之功能0DH/0CH来读/写象素,则它可屏蔽掉各种显示模式的差异,用同样的参数完成同样的功能。
所以,在此建议:
使用系统中断的方法来实现对图形象素的操作。
(3)、256色320×200图形显示模式
表达256种不同颜色需要8位二进制,即一个字节。
在该模式下,其显示缓冲区的存储方式是非常简单的,即:
第一个字节存储第一个象素的颜色,第二个字节存储第二个象素的颜色,以此类推,所以,存储满屏象素所需要的字节数为:
320×200×1=64000。
其显示缓冲区的存储方式如图8.10所示。
从上面三种不同图形显示模式的介绍,不难看出:
各种显示模式在显示缓冲区存储方式上的明显差异,操作象素方法的难易程度相差也很大,所以,再次建议:
程序员不要用直接操作显示缓冲区的办法来达到改变显示象素的目的,最好是通过BIOS内的中断功能来实现相应的功能,这样,所编写的程序能很方便地适应不同的图形显示模式。
2、显示缓冲区
显示缓冲区是用来记录屏幕显示信息的。
在文本显示方式下,这些显示信息包括:
每个显示字符的ASCII码及其显示属性,如图8.7所示。
在图形显示方式下,显示缓冲区内存储每