1、汇编语言课件,王爽 著清华大学出版社,制作工具:Microsoft PowerPoint2003,本课件由汇编网()制作提供,第15章 外中断,15.1 接口芯片和端口 15.2 外中断信息 15.3 PC机键盘的处理过程 15.4 编写int 9中断例程 15.5 安装新的int 9中断例程,引言,以前我们讨论的都是CPU对指令的执行。我们知道,CPU 在计算机系统中,除了能够执行指令,进行运算以外,还应该能够对外部设备进行控制,接收它们的输入,向它们进行输出。 也就是说,CPU 除了有运算能力外,还要有 I/O( Input/Output ,输入/输出)能力。,15.1 接口芯片和端口,第
2、14 章我们讲过,在PC 系统的接口卡和主板上,装有各种接口芯片。这些外设接口芯片的内部有若干寄存器,CPU 将这些寄存器当作端口来访问。,15.1 接口芯片和端口,外设的输入不直接送入内存和CPU ,而是送入相关的接口芯片的端口中; CPU 向外设的输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设。,15.1 接口芯片和端口,CPU 还可以向外设输出控制命令,而这些控制命令也是先送到相关芯片的端口中,然后再由相关的芯片根据命令对外设实施控制。可见,CPU 通过端口和外部设备进行联系。,15.2 外中断信息,CPU 在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程
3、,处理外设的输入。 在PC 系统中,外中断源一共有两类: 1、可屏蔽中断 2、不可屏蔽中断,15.2 外中断信息,可屏蔽中断是CPU 可以不响应的外中断。CPU 是否响应可屏蔽中断,要看标志寄存器的IF 位的设置。 当CPU 检测到可屏蔽中断信息时: 如果IF=1,则CPU 在执行完当前指令后响应中断,引发中断过程; 如果IF=0,则不响应可屏蔽中断。,15.2 外中断信息,我们回忆一下内中断所引发的中断过程:(1)取中断类型码n;(2)标志寄存器入栈,IF=0,TF=0;(3)CS 、IP 入栈;(4)(IP)=(n*4),(CS)=(n*4+2)由此转去执行中断处理程序。,15.2 外中断
4、信息,可屏蔽中断所引发的中断过程 ,除在第1步的实现上有所不同外,基本上和内中断的中断过程相同。 因为可屏蔽中断信息来自于CPU外部,中断类型码是通过数据总线送入CPU 的; 而内中断的中断类型码是在CPU内部产生的。,15.2 外中断信息,现在,我们可以解释中断过程中将IF置为0的原因了。将IF置0的原因就是,在进入中断处理程序后,禁止其他的可屏蔽中断。 当然,如果在中断处理程序中需要处理可屏蔽中断,可以用指令将IF 置1 。,15.2 外中断信息,8086CPU 提供的设置IF的指令如下: sti,用于设置IF=1; cli,用于设置IF=0。,15.2 外中断信息,不可屏蔽中断是CPU
5、必须响应的外中断。当CPU 检测到不可屏蔽中断信息时,则在执行完当前指令后,立即响应,引发中断过程。 对于8086CPU 不可屏蔽中断的中断类型码固定为2。所以中断过程中,不需要取中断类型码。,15.2 外中断信息,不可屏蔽中断的中断过程: 1、标志寄存器入栈,IF=0,TF=0; 2、CS、IP入栈; 3、(IP)=(8),(CS)=(0AH)。,15.2 外中断信息,几乎所有由外设引发的外中断,都是可屏蔽中断。当外设有需要处理的事件(比如说键盘输入)发生时,相关芯片向CPU 发出可屏蔽中断信息。 不可屏蔽中断是在系统中有必须处理的紧急情况发生时用来通知CPU 的中断信息。在我们的课程中,主
6、要讨论可屏蔽中断。,15.3 PC机键盘的处理过程,下面我们看一下键盘输入的处理过程,并以此来体会一下PC 机处理外设输入的基本方法。 1、键盘输入 2、引发9号中断 3、执行int 9中断例程,15.3 PC机键盘的处理过程,键盘上的每一个键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。 按下一个键时,开关接通,该芯片就产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60H 。 松开按下的键时,也产生一个扫描码,扫描码说明了松开的键在键盘上的位置。松开按键时产生的扫描码也被送入60H 端口中。,15.
7、3 PC机键盘的处理过程,一般将按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。 扫描码长度为一个字节,通码的第7 位为 0 ,断码的第7位为1,即: 断码=通码80H 比如:g键的通码为22H,断码为a2H。 键盘上部分键的扫描码,15.3 PC机键盘的处理过程,15.3 PC机键盘的处理过程,键盘的输入到达60H 端口时,相关的芯片就会向CPU 发出中断类型码为 9 的可屏蔽中断信息。 CPU检测到该中断信息后,如果IF=1,则响应中断,引发中断过程,转去执行int 9中断例程。,15.3 PC机键盘的处理过程,BIOS 提供了int 9中断例程,用来进行基木的键盘输入处
8、理,主要的工作如下: (1)读出60H 端口中的扫描码;,15.3 PC机键盘的处理过程,(2)如果是字符键的扫描码,将该扫描码和它所对应的字符码( 即 ASCII码)送入内存中的 BIOS 键盘缓冲区;如果是控制键(比如 Ctrl )和切换键(比如 CapsLock)的扫描码,则将其转变为状态字节( 用二进制位记录控制键和切换键状态的字节 )写入内存中存储状态字节的单元。,15.3 PC机键盘的处理过程,(3)对键盘系统进行相关的控制,比如说,向相关芯片发出应答信息。 PC机键盘的处理过程演示,15.3 PC机键盘的处理过程,BIOS键盘缓冲区是系统启动后,BIOS用于存放int 9 中断例
9、程所接收的键盘输入的内存区。 该内存区可以存储15 个键盘输入,因为 int 9 中断例程除了接收扫描码外,还要产生和扫描码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。,15.3 PC机键盘的处理过程,0040:17 单元存储键盘状态字节,该字节记录了控制键和切换键的状态。键盘状态字节各位记录的信息如下:,15.4 编写int 9 中断例程,从上面的内容中,我们可以看出键盘输入的处理过程: (1)键盘产生扫描码; (2)扫描码送入60h 端口; (3)引发9 号中断; (4)CPU执行int 9中断例程处理键盘输入。,15.4
10、 编写int 9 中断例程,上面的过程中,第(1)、(2)、(3)步都是由硬件系统完成的。我们能够改变的只有int 9中断处理程序。 我们可以重新编写int 9中断例程,按照自己的意图来处理键盘的输入。,15.4 编写int 9 中断例程,但是,在课程中,我们不准备完整地编写一个键盘中断的处理程序,因为要涉及到一些硬件细节,而这些内容脱离了我们的内容主线。 但是,我们却还要编写新的键盘中断处理程序,来进行一些特殊的工作,那么这些硬件细节如何处理呢?,15.4 编写int 9 中断例程,这点比较简单,因为BIOS 提供的int 9中断例程已经对这些硬件细节进行了处理。 我们只要在自己编写的中断例
11、程中调用BIOS 的int 9中断例程就可以了。 编程,15.4 编写int 9 中断例程,编程: 在屏幕中间依次显示 “a”“z” ,并可以让人看清。在显示的过程中,按下Esc键后,改变显示的颜色。我们先来看一下如何依次显示“a”“z”,15.4 编写int 9 中断例程,assume cs:code code segment start: mov ax,0b800hmov es,axmov ah,as: mov es:160*12+40*2,ahinc ahcmp ah,zjna smov ax,4c00hint 21h code ends end start,依次显示”a”z”,15.4
12、 编写int 9 中断例程,在上面的程序的执行过程中,我们无法看清屏幕上的显示。 因为一个字母刚显示到屏幕上,CPU执行几条指令后,就又变成了另一个字母,字母之间切换得太快,无法看清。,15.4 编写int 9 中断例程,我们应该在每显示一个字母后,延时一段时间,让人看清后,再显示下一个字母。 那么如何延时呢?我们让CPU 执行一段时间的空循环。,15.4 编写int 9 中断例程,因为现在CPU 的速度都非常快,所以循环的次数一定要大,我们用两个16 位寄存器来存放32 位的循环次数。如下:,mov dx,10hmov ax,0s: sub ax,1sbb dx,0cmp ax,0jne s
13、cmp dx,0jne s,15.4 编写int 9 中断例程,上面的程序,循环100000h 次。 我们可以将循环延时的程序段写为一个子程序。 现在,我们看程序源代码,15.4 编写int 9 中断例程,显示“a”“z”,并可以让人看清,这个任务己经实现。 那么如何实现,按下 Esc 键后,改变显示的颜色呢? 键盘输入到达60h 端口后,就会引发 9号中断,CPU 则转去执行int 9中断例程。,15.4 编写int 9 中断例程,我们可以编写int 9中断例程,功能如下: (1)从60h 端口读出键盘的输入; (2)调用BIOS 的int 9 中断例程,处理其他硬件细节; (3)判断是否为
14、Esc的扫描码,如果是,改 变显示的颜色后返回;如果不是则直接返回。 我们对这些功能的实现一一进行分析,15.4 编写int 9 中断例程,1、从端口60h读出键盘的输入in al,60h,15.4 编写int 9 中断例程,2、调用BIOS的int 9中断例程 有一点要注意的是,我们写的中断处理程序要成为新的int 9中断例程,主程序必须要将中断向量表中的int 9中断例程的入口地址改为我们写的中断处理程序的入口地址。,15.4 编写int 9 中断例程,那么在新的中断处理程序中调用原来的int 9中断例程时,中断向量表中的int 9中断例程的入口地址却不是原来的int 9 中断例程的地址。
15、 所以我们不能使用int 指令直接调用。,15.4 编写int 9 中断例程,要能在我们写的新中断例程中调用原来的中断例程,就必须在将中断向量表中的中断例程的入口地址改为新地址之前,将原来的入口地址保存起来。 这样,在需要调用的时候,我们才能找到原来的中断例程的入口。,15.4 编写int 9 中断例程,对于我们现在的问题,假设我们将原来int 9中断例程的偏移地址和段地址保存在ds:0和ds:2单元中。 那么我们在需要调用原来的int 9中断例程时候,就可以在 ds:0、ds:2 单元中找到它的入口地址。,15.4 编写int 9 中断例程,那么,有了入口地址后,我们如何进行调用呢? 当然不
16、能使用指令int 9来调用。我们可以用别的指令来对int指令进行一些模拟,从而实现对中断例程的调用。,15.4 编写int 9 中断例程,我们来看,int 指令在执行的时候,CPU 进行下面的工作: (1)取中断类型码n; (2)标志寄存器入栈; (3) IF=0,TF=0; (4) CS 、IP 入栈; (5)(IP)=(n*4),(CS=(n*4+2)。,15.4 编写int 9 中断例程,取中断类型码是为了定位中断例程的入口地址,在我们的问题中,中断例程的入口地址已经知道。 所以,我们用别的指令模拟int指令时候,不需要做第(1)步。,15.4 编写int 9 中断例程,在假设要调用的中
17、断例程的入口地址在ds:0和ds:2单元中的前提下,我们将int 过程用下面几步模拟:(1)标志寄存器入栈;(2)IF=0,TF=0;(3)CS、IP入栈;(4)(IP)=(ds)*16+0),(CS)=(ds)*16+2)。,15.4 编写int 9 中断例程,可以注意到第(3)、(4)步和call dword ptr ds:0的功能一样。 call dword ptr ds:0的功能也是: (1)CS 、IP 入栈; (2)(IP)=(ds)*16+0), (CS)=(ds)*16+2)。 如果还有疑问,复习10.6节的内容。,15.4 编写int 9 中断例程,所以int 过程的模拟过程
18、变为:(1)标志寄存器入栈;(2)IF=0,TF=0;(3)call dword ptr ds:0对于(1),可用pushf实现。对于(2),可用下面的指令实现。,15.4 编写int 9 中断例程,实现IF=0,TF=0步骤:pushfpop axand ah,11111100b ;IF和OF为标志寄存器的第9位和第8位push axpopf 这样,模拟int指令的调用功能,调用入口地址在ds:0、ds:2中的中断例程的程序如下,15.4 编写int 9 中断例程,pushf ;标志寄存器入栈pushfpop axand ah,11111100b ;IF和OF为标志寄存器的第9位和第8位pu
19、sh axpopf ;IF=0、TF=0call dword ptr ds:0;CS、IP入栈: ;(IP)=(ds)*16+0), ;(CS)=(ds)*16+2),15.4 编写int 9 中断例程,3、如果是Esc键的扫描码,改变显示的颜色后返回 如何改变显示的颜色?,15.4 编写int 9 中断例程,显示的位置是屏幕的中问,即第12行40列,显存中的偏移地址为:160*12+40* 2。 所以字符的ASCII码要送入b800:160*12+40*2处。 而b800:160*12+40*2+1处是字符的属性,我们只要改变此处的数据就可以改变在b800:160*12+40*2处显示的字符
20、的颜色了。,15.4 编写int 9 中断例程,该程序的最后一个问题是,要在程序返回前,将中断向量表中的ini 9中断例程的入口地址恢复为原来的地址。否则程序返回后,别的程序将无法使用键盘。 经过分析,整理得到完整的程序代码。,15.4 编写int 9 中断例程,注意,本章中所有关于键盘的程序,因要直接访问真实的硬件,则必须在DOS实模式下运行。 在Windows 2000 的DOS 方式下运行,会出现一些和硬件工作原理不符合的现象。,特别提示,检测点15.1(page271)没有通过此检测点,请不要向下进行!,15.5 安装新的 int 9 中断例程,下面,我们安装一个新的int 9中断例程
21、,使得原int 9中断例程的功能得到扩展。 任务:安装一个新的int 9中断例程,功能:在DOS下,按F1键后改变当前屏幕的显示颜色,其他的键照常处理。 我们进行一下分析,15.5 安装新的 int 9 中断例程,分析:(1)改变屏幕的显示颜色改变从B800开始的4000个字一节中的所有奇地址单元中的内容,当前屏幕的显示颜色即发生改变。程序如下,15.5 安装新的 int 9 中断例程,分析(续):(1)改变屏幕的显示颜色程序,mov ax,0b800hmov es,axmov bx,1mov cx,2000s: inc byte ptr es:bxadd bx,2loop s,15.5 安装
22、新的 int 9 中断例程,(2)其他键照常处理可以调用原int 9中断处理程序,来处理其他的键盘输入。,15.5 安装新的 int 9 中断例程,分析(续) :(3)原int 9中断例程入口地址的保存因为在编写的新int 9中断例程中要调用原int 9中断例程,所以,要保存原int 9中断例程的入口地址。保存在哪里?,15.5 安装新的 int 9 中断例程,分析(续) :显然不能保存在安装程序中,因为安装程序返回后地址将丢失。我们将地址保存在0:200单元处。,15.5 安装新的 int 9 中断例程,分析(续) :(4)新int 9中断例程的安装这个问题在前面己经详细讨论过。我们可将新的
23、int 9中断例程安装在0:204 处。完整的程序代码,15.5 安装新的 int 9 中断例程,这一章中,我们通过对键盘输入的处理,讲解了CPU 对外设输入的通常处理方法。即: (1)外设的输入送入端口; (2)向CPU 发出外中断(可屏蔽中断)信息; (3)CPU检测到可屏蔽中断信息,如果IF=1,CPU在执行完当前指令后响应中断,执行相应的中断例程; (4)可在中断例程中实现对外设输入的处理。,15.5 安装新的 int 9 中断例程,端口和中断机制,是CPU 进行I/O的基础。,15.5 安装新的 int 9 中断例程,指令系统总结我们对8086CPU 的指令系统进行一下总结。读者若要
24、详细了解8086 指令系统中的各个指令的用法 ,可以查看有关的指令手册。 8086CPU 提供以下几大类指令,15.5 安装新的 int 9 中断例程,1、数据传送指令比如:mov、push、pop、pushf、popf、xchg等都是数据传送指令,这些指令实现寄存器和内存、寄存器和寄存器之间的单个数据传送。,15.5 安装新的 int 9 中断例程,2、算术运算指令比如:add、sub、adc、sbb、inc、dec、cmp、imul、idiv、aaa等都是算术运算指令,这些指令实现寄存器和内存中的数据的算数运算。它们的执行结果影响标志寄存器的:sf、zf、of、cf、pf、af位。,15.
25、5 安装新的 int 9 中断例程,3、逻辑指令比如:and、or、not、xor、test、shl、shr、sal、sar、rol、ror、rcl、rcr 等都是逻辑指令。除了not指令外,它们的执行结果都影响标志寄存器的相关标志位。,15.5 安装新的 int 9 中断例程,4、转移指令可以修改IP ,或同时修改CS 和IP 的指令统称为转移指令。转移指令分为以下几类:(1)无条件转移指令,比如:jmp;(2)条件转移指令,比如:jcxz、je、jb、ja、jnb、jna等;(3)循环指令,比如:loop;(4)过程,比如:call、ret、retf;(5)中断,比如int、iret。,15.5 安装新的 int 9 中断例程,5、处理机控制指令 这些指令对标志寄存器或其他处理机状态进行设置,比如:cld、std、cli、sti、nop、clc、cmc、stc、hlt、wait、esc、lock等都是处理机控制指令。,15.5 安装新的 int 9 中断例程,6、串处理指令这些指令对内存中的批量数据进行处理比如:movsb、movsw、cmps、scas、lods、stos等。若要使用这些指令方便地进行批量数据的处理,则需要和rep、repe、repne等前缀指令配合使用。,小结,