王爽 《汇编语言》 读书笔记 十五 外中断

时间:2021-01-16 00:44:11

第十五章 外中断

体现了cpu的I/O能力。

1)cpu如何得知外设输入了?

2)cpu如何得到外设的输入?


15.1 接口芯片和端口

cpu通过端口和外部设备进行联系


15.2 外中断信息

外部设备通过外中断来通知cpu 引发中断过程,处理外设的输入。


外中断源:

1. 可屏蔽中断

可屏蔽中断是cpu可以不响应的外中断。 例如IF =1 则cpu会响应可屏蔽中断,如果IF=0 cpu则不响应

内中断引发的中断过程:

1)取中断类型码n;

2)标志寄存器入栈, IF=0, TF=0

3)  CS,IP入栈

4)(IP)=(n*4), (CS) = (n*4 + 2)


如果需要接受可屏蔽外部中断设置IF =1

sti;  if = 1

cli; if = 0


(std; df = 1

cld; df = 0)

2. 不可屏蔽中断

在8086中,不可屏蔽中断固定为2.,不需要取中断类型码

1) 标志寄存器入栈,IF=0, TF=0

2) CS, IP入栈

3)(IP) = (8),  (CS) = (0AH)


15.3 PC机键盘的处理过程

1. 键盘输入

按下和松开按键产生扫描码

存放在端口60h

按键产生通码;松开一个键产生断码。扫描码长度为1个字节,通码第七位是0 ,断码第七位是1


断码 = 通码 + 80h

2. 引发9号中断

有键盘输入,除了在端口60h存放相应的扫描码,还会向cpu发送INT 9 中断。

3. 执行int 9 中断的例程

BIOS中有中断9的例程,用来进行基本的键盘输入处理。



15.4 编写int 9 中断例程

1)键盘产生扫描码

2)扫描码送入60h端口

3)引发9号中断

4)cpu执行int9中断例程处理键盘输入。

编程:在屏幕依次显示 a~z ,并且可以让人看清。在显示过程中,按下ESC键后,改变现实颜色。


运行代码如下


assume cs:code
stack segment
	db 128 dup (0)
stack ends

code segment
start:		mov ax, stack
			mov ss, ax
			mov sp, 128
			
			mov ax, 0b800h
			mov es, ax
			mov ah, 'a'
		s:	mov es:[160*12 + 40*2], ah
			call delay
			inc ah
			cmp ah, 'z'
			jna s
			
			
			mov ax, 4c00h
			int 21h
			
delay:		pushf
			push ax
			push dx
			
			mov dx, 2000h		; loop for 10,000,000h times
			mov ax, 0
	nextd:	sub ax, 1
			sbb dx, 0
			cmp ax, 0
			jne nextd
			cmp dx, 0
			jne nextd
			pop dx
			pop ax
			popf
			ret
code ends

end start
接下来要编写装载int9点程序

1. 从端口60h读入键盘输入

2 调用bios的int9 中断例程

模拟中断例程的过程

假设事先将INT9的入口地址放在ds:0 和ds:2

1)标志寄存器入栈

2)IF=0,TF=0 屏蔽外部中断和单步调试中断

3)CS, IP入栈

4)(IP)=((16)*16 + 0), (cs) = (16*(ds) + 2)


pushf


pushf

pop ax

and ah, 1111 1100b

push ax

popf

call dword ptr ds:[0]

3. 

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
			
			; store the original int9 entry address of system
			mov ax, 0
			mov es, ax
			
			push es:[9 * 4]
			pop ds:[0]
			push es:[9 * 4 + 2]
			pop ds:[2]
			
			; set the new irq procedure for int9
			mov word ptr es:[9*4], offset int9
			mov es:[9 * 4 + 2], cs
			
			mov ax, 0b800h
			mov es, ax
			mov ah, 'a'
		s:	mov es:[160 * 12 + 40 * 2], ah
			call delay
			inc ah
			cmp ah, 'z'
			jna s
			
			; restore the entry address for int9 of system.
			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 sub procedure			
delay:		pushf
			push ax
			push dx
			
			mov dx, 1000h		; loop for 10,000,000h times
			mov ax, 0
	nextd:	sub ax, 1
			sbb dx, 0
			cmp ax, 0
			jne nextd
			cmp dx, 0
			jne nextd
			pop dx
			pop ax
			popf
			ret
			
; sub procedure for int9
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]	;call the original int9 procedure of System
			
			cmp al, 1				; use has press the esc . 1 is the scan code for ESC
			jne int9ret
			
			mov ax, 0b800h
			mov es, ax
			inc byte ptr es:[160 * 12 + 40 * 2 +1]	; change color
			
int9ret:	pop es
			pop bx
			pop ax
			iret
			
code ends

end start


运行结果:


王爽 《汇编语言》 读书笔记 十五 外中断

增加了安全机制在设置INT9向量地址的时候防止相应了外部中断而导致程序运行错误。

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
			
			; store the original int9 entry address of system
			mov ax, 0
			mov es, ax
			
			push es:[9 * 4]
			pop ds:[0]
			push es:[9 * 4 + 2]
			pop ds:[2]
			
			; set the new irq procedure for int9
			
			cli		; ignore the outside irq
			mov word ptr es:[9*4], offset int9
			mov es:[9 * 4 + 2], cs
			sti		; restore the IF flag.
			
			mov ax, 0b800h
			mov es, ax
			mov ah, 'a'
		s:	mov es:[160 * 12 + 40 * 2], ah
			call delay
			inc ah
			cmp ah, 'z'
			jna s
			
			; restore the entry address for int9 of system.
			mov ax, 0
			mov es, ax
			
			cli		; ignore the outside irq
			push ds:[0]
			pop es:[9 * 4]
			push ds:[2]
			pop es:[9 * 4 + 2]
			sti		; restore the IF flag.
			
			mov ax, 4c00h
			int 21h
; delay sub procedure			
delay:		pushf
			push ax
			push dx
			
			mov dx, 1000h		; loop for 10,000,000h times
			mov ax, 0
	nextd:	sub ax, 1
			sbb dx, 0
			cmp ax, 0
			jne nextd
			cmp dx, 0
			jne nextd
			pop dx
			pop ax
			popf
			ret
			
; sub procedure for int9
int9:		push ax
			push es
			
			in al, 60h
			
			pushf
			
			call dword ptr ds:[0]	;call the original int9 procedure of System
			
			cmp al, 1				; use has press the esc . 1 is the scan code for ESC
			jne int9ret
			
			mov ax, 0b800h
			mov es, ax
			inc byte ptr es:[160 * 12 + 40 * 2 +1]	; change color
			
int9ret:	pop es
			pop ax
			iret
			
code ends

end start

15.5 安装新的int9 中断例程

任务:安装一个新的int9 中断例程

功能:在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

						; set es:di as target address 0000:0200h
			mov ax, 0
			mov es, ax
			mov di, 204h
							; set ds:si as source address cs:sqr
			mov ax, cs
			mov ds, ax
			mov si, offset int9
							; set cx as the data length
			mov cx, offset int9end - offset int9
							; set the transport directive DF = 0 cld
			cld
			rep movsb
			
			; store the original entry cs:ip of int9 to 0:200
			push es:[9 * 4]
			pop es:[200h]
			push es:[9 * 4 + 2]
			pop es:[202h]

			; set the IRQ table  1F0 = 200h(IP)    1F2 = 0(CS)
			mov ax, 0
			mov es, ax
			cli		; ignore the outside irq
			mov word ptr es:[9 * 4], 204h
			mov word ptr es:[9 * 4 + 2], 0
			sti		; restore the outside irq.
			
			mov ax, 4c00h
			int 21h


; sub procedure for int9
int9:  		push ax
			push bx
			push cx
			push es
			
			in al, 60h
			
			pushf
			
			call dword ptr cs:[200h]	;call the original int9 procedure of System
			
			cmp al, 3bh				; scan code for F1
			jne int9ret
			
			mov ax, 0b800h
			mov es, ax
			mov bx, 1
			mov cx, 2000
	int9s:	inc byte ptr es:[bx]	; change color
			add bx, 2
			loop int9s
			
int9ret:	pop es
			pop cx
			pop bx
			pop ax
			iret
int9end:	nop
code ends
end start

运行结果

王爽 《汇编语言》 读书笔记 十五 外中断


实验15 安装新的int9 中断例程

功能:在dos下,按下F2键,除非不再松开,如果松开,显示满屏幕的 A。 (原书的例子是A键,但是这会影响正常的输入)

 

assume cs:code
stack segment
	db 128 dup (0)
stack ends
code segment
start:		mov ax, stack
			mov ss, ax
			mov sp, 128

						; set es:di as target address 0000:0200h
			mov ax, 0
			mov es, ax
			mov di, 204h
							; set ds:si as source address cs:sqr
			mov ax, cs
			mov ds, ax
			mov si, offset int9
							; set cx as the data length
			mov cx, offset int9end - offset int9
							; set the transport directive DF = 0 cld
			cld
			rep movsb
			
			; store the original entry cs:ip of int9 to 0:200
			push es:[9 * 4]
			pop es:[200h]
			push es:[9 * 4 + 2]
			pop es:[202h]

			; set the IRQ table  1F0 = 200h(IP)    1F2 = 0(CS)
			mov ax, 0
			mov es, ax
			cli		; ignore the outside irq
			mov word ptr es:[9 * 4], 204h
			mov word ptr es:[9 * 4 + 2], 0
			sti		; restore the outside irq.
			
			mov ax, 4c00h
			int 21h


; sub procedure for int9
int9:  		push ax
			push bx
			push cx
			push es
			
			in al, 60h
			
			pushf
			
			call dword ptr cs:[200h]	;call the original int9 procedure of System
			
			cmp al, 0bch				; scan code for release F2
			jne int9ret
			
			mov ax, 0b800h
			mov es, ax
			mov bx, 0
			mov cx, 2000
			mov al, 'A'
	int9s:	mov es:[bx], al	; ptint A
			add bx, 2
			loop int9s
			
int9ret:	pop es
			pop cx
			pop bx
			pop ax
			iret
int9end:	nop
code ends
end start
运行结果

王爽 《汇编语言》 读书笔记 十五 外中断