|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 若余相思 于 2017-12-5 16:24 编辑
这章将学习外中断,外中断就是CPU对于外部中断的处理,比如:键盘的输入
要及时处理外设的输入,显然需要解决两个问题:
(1)外设的输入输出随时可能发生,CPU如何得知?
(2)CPU如何得到外设的输入
15.1节 接口芯片和端口
外设的输入不直接送入内存和CPU,而是送入相关的接口芯片的端口中,
CPU向外设的输出也不是直接送入外设,而是先送入端口,再有相关的芯片送到外设
可见,CPU通过端口和外部设备进行联系
15.2节 外中断信息
外中断源一共分位两种
1、可屏蔽中断
2、不可屏蔽中断
在可屏蔽中断中,CPU可以不响应中断,响不响应主要看IF位,IF位为1
则CPU要响应这个可屏蔽中断,IF为0可以不响应
如下指令设置IF的值
sti 设置IF = 1
cli 设置IF = 0
在不可屏蔽中断中,CPU必须立即响应该中断,不可屏蔽中断的类型码固定为2,
所在中断过程中可以不取中断类型码
不可屏蔽中断是系统在有必要处理的紧急情况发生时来通知CPU的中断信心,在课程中主要讲解可屏蔽中断
15.3节 PC机键盘处理过程
1、键盘输入
当你在键盘上按下一个字符时,就会产生扫描码(通码),扫描码被送入寄存器,该寄存器的端口为60H;你在松开一个键盘字符时也会产生扫描码(断码),也是被送入60H端口。
断码= 通码+ 80H
如:g键的通码为22H,则断码为a2h。
下面列出键盘部分扫描码:
2、引发int9中断
键盘的输入到达了60h端口时,相关芯片就会向CPU发出类型码为9的可屏蔽中断,如果IF = 1,则响应中断。
15.4节 编写int9中断例程
编程:在屏幕一次显示"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]
- pop ds:[0]
- push es:[9 * 4 + 2]
- pop ds:[2]
-
- mov word ptr es:[9 * 4 ], offset int9
- mov word ptr es:[9 * 4 + 2], cs
-
-
- mov ax, 0b800h
- mov es, ax
- mov ah, 'a'
- s: mov es:[160 * 12 + 80 ], ah
- call delay
- inc ah
- cmp ah, 'z'
- jna s
-
- mov ax, 4c00H
- int 21H
-
- 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 ax, 0
- mov dx, 1000H
-
- s1: sub ax, 1
- sbb dx, 0
- cmp ax, 0
- jne s1
- cmp dx, 0
- jne s1
-
- pop dx
- pop ax
- ret
-
- int9: push ax
- push bx
- push es
-
- in al, 60H
-
- pushf
-
- pushf
- pop bx
- and bh, 11111100b
- push bx
- popf
-
- call dword ptr ds:[0]
-
- cmp al, 1
- jne int9ret
-
- mov ax, 0b800h
- mov es, ax
- inc byte ptr es:[12*160 + 80 + 1]
-
- int9ret: pop es
- pop bx
- pop ax
- iret
-
-
-
- code ends
- end start
-
-
-
复制代码
写虽然困难,但是理解了就觉得挺简单的
在接着15.5节的编程
代码:
- 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
复制代码
|
|