汇编语言_第15章 外中断

15.1 接口芯片和端口

  • CPU通过端口和外部设备进行联系。

    外设的输入不直接送入内存和CPU ,而是送入相关的接口芯片的端口中;
    CPU向外设的输出也不是直接送入外设,而是先送入端口中,在由相关芯片送到外设;

15.2 外中断信息
外中断源分为以下2类:
1.可屏蔽中断
可屏蔽中断是 CPU可以不响应的外中断。

  • 当CPU检测到可屏蔽中断信息时,
    如果IF=1,则CPU在执行完当前指令后响应中断,引发中断过程;
    如果IF=0,则不响应可屏蔽中断。

  • 中断过程中将IF设置为0的原因:
    在进入中断处理程序后,禁止其他的可屏蔽中断。

  • 8086CPU 提供的设置IF的指令:

    sti,设置IF=1;
    cli,设置IF=0.

2.不可屏蔽中断
不可屏蔽中断是CPU 必须响应的外中断。当CPU检测到不可屏蔽中断信息时,则在执行完当前指令后,立即响应,引发中断过程。

  • 对于8086CPU,不可屏蔽中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码。不可屏蔽中断的中断过程如下:
    (1) 标志寄存器入栈,IF=0,TF=0;
    (2) CS、IP入栈;
    (3) (IP)=(8),(CS)=(0AH).

15.3 PC机键盘的处理过程
1.键盘输入

  • 键盘上的每一个键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。
  • 按下一个键是,开关接通,该芯片就产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60h。
  • 松开按下的键时,也产生一个扫描码,扫描码说明了松开的键在键盘上的位置。松开按键时产生的扫描码也被送入60h端口中。
  • 一般将按下一个键时产生的扫描码称为 通码,松开一个按键产生的扫描码称为 断码。扫描码长度为1个字节,通码 的第7位为0,断码的第7位为1,即:
    断码=通码+80h
    在这里插入图片描述
    在这里插入图片描述

2.引发9号中断

  • 键盘的输入到达60h端口时,相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息。CPU检测到该中断信息后,如果IF=1,则响应中断,引发中断过程,转去执行int 9中断例程。

3.执行int 9 中断例程

  • BIOS 提供了int 9 中断例程,用来进行基本的键盘输入处理。主要工作如下:
    (1) 读出60h端口中的扫描码;
    (2)

    • 如果是字符键的扫描码,将该扫描码和它所对应的字符码(即ASCII码)送入内存中的BIOS键盘缓冲区;
    • 如果是控制键(如Ctrl)和切换键(如CapsLock)的扫描码,则将其转变为状态字节(用二进制记录控制键和切换键状态的字节)写入内存中存储状态字节的单元;

(3) 对键盘进行相关的控制,如,向相关芯片发出应答信息。

  • BIOS 键盘缓冲区是系统启动后,BIOS用于存放int 9 中断例程所接收的键盘输入的内存区。该内存区可以存储15个键盘输入,因为int 9 中断例程除了接收扫描码外,还要产生和扫描码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用1个字单元存放,高位字节存放扫描码,低位字节存放字符码
  • 0040:17 单元存储键盘状态字节,该字节记录了控制键和切换键的状态。
  • 键盘状态字节各位记录的信息如下:
    在这里插入图片描述

15.4 编写int 9 中断例程
键盘输入的处理过程:
①键盘产生扫描码;
②扫描码送入60h端口;
③引发9号中断;
④CPU执行 int 9 中断例程梳理键盘输入。
编程,在屏幕中间显示a~z,并可以让人看清,在显示的过程中,按下Esc键后,改变显示的颜色。

assume cs:code

	stack segment
		db 128 dup(0)
	stack ends
	
	data segment
		dw 0,0
	data ends
	
	code segment
	start:	mov ax,stack
			mov ss,ax
			mov sp,128
			
			mov ax,data
			mov ds,ax
			
			mov ax,0
			mov es,ax
			
			push es:[9*4]		;(IP)=(N*4),(CS)=(N*4+2)
			pop ds:[0]
			push es:[9*4+2]
			pop ds:[2]			;将原来的int 9 中断例程的入口地址保存在ds:0\ds:2单元中
			
			mov word ptr es:[9*4],offset int9
			mov es:[9*4+2],cs	;在中断向量表中设置新的int 9 中断例程入口地址
	
			mov ax,0b800h		;依次显示a~z
			mov es,ax
			mov ah,'a'
		s:	mov es:[160*12+40*2],ah
			call delay
			inc ah				
			cmp ah,'z'			;根据2值相减结果修改标志寄存器相应位
			jna s				;jna 不大于,如果ah的值≤ z的ASCII码值 跳转到s
			
			mov ax,0
			mov es,ax
			
			push ds:[0]
			pop es:[9*4]
			push ds:[2]
			pop es:[9*4+2]
			
			mov ax,4c00h
			int 21h
			
	delay:	push ax
			push dx
			mov dx,0010h	;循环100000h次
			mov ax,0
		s1:	sub ax,1		;(ax)=(ax)-1
			sbb dx,0		;借位减,(dx)=(dx)-0-CF
			cmp ax,0		
			jne s1			;(ax)≠0 转到s1
			cmp dx,0
			jne s1			;(dx)≠0 转到s1
			pop dx
			pop ax
			ret
					
	int9:	push ax
			push bx
			push es
			
			in al,60
			
			pushf
			pushf
			pop bx
			and bh,11111100b
			push bx
			popf
			call dword ptr ds:[0]	;对int 指令进行模拟,调用原来的int 9中断例程
			
			
			cmp al,1
			jne int9ret
			
			mov ax,0b800h
			mov es,ax
			inc byte ptr es:[160*12+40*2+1]	;将属性值+1改变颜色
			
	int9ret:pop es
			pop bx
			pop ax
			iret
					
	code ends
	end start
	

15.5 安装新的int9 中断例程
任务:安装一个新的int 9 中断例程
功能:在DOS 下,按F1键后改变当前屏幕的显示颜色,其他的键照常处理。

assume cs:code

	stack segment
		db 128 dup(0)
	stack ends
	
	code segment
	start:	mov ax,stack
			mov ss,ax
			mov sp,128
			
			push cs
			pop ds
			
			mov ax,0
			mov es,ax
			
			mov si,offset int9		;设置ds:si指向源地址
			mov di,204h 			;设置es:di指向目的地址
			mov cx,offset int9end-offset int9 ;设置cx为传输长度
			cld						;设置传送方向为正
			rep movsb
			
			push es:[9*4]
			pop es:[200h]
			push es:[9*4+2]
			pop es:[202h]
			
			cli
			mov word ptr es:[9*4],204h
			mov word ptr es:[9*4+2],0
			sti
			
			mov ax,4c00h
			int 21h

	int9:	push ax
			push bx
			push cx
			push es
			
			in al,60h
			
			pushf
			call dword ptr cs:[200h]	;当此中断例程执行时(CS)=0
			
			cmp al,3bh					;F1的扫描码为3bh
			jne int9ret
			
			mov ax,0b800h
			mov es,ax
			mov bx,1
			mov cx,2000
		s:	inc byte ptr es:[bx]
			add bx,2
			loop s
	int9ret:pop es
			pop cx
			pop bx
			pop ax
			iret
			
	int9end:nop
	
	code ends
	end start

To be continue…

猜你喜欢

转载自blog.csdn.net/madao1234/article/details/84609221