蒙珣的博客

活好当下,做好今天该做的事情。

0%

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

外中断不可屏蔽中断,中断类型码为2

1
2
3
4
5
pushf
IF = 0 TF = 0
push cs
push ip
ip = 2*4 cs = 2*4+2

外中断可屏蔽中断,和内中断一样

1
2
3
4
5
6
;1.获取中断类型码
;2.pushf
;3.IF = 0 TF = 0
push cs
push ip
IP = n*4 cs = n*4+2

编程:在屏幕中间依次显示”a-z”,并可以让人看清,在显示过程中,按下esc键后,改变显示颜色,依次显示”a-z”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code
code segment

start: mov ax,0b800h
mov es,ax
mov ah,'a'

s: mov es:[160*12+40*2],ah
inc ah
cmp ah,'z'
jna s
mov ax,4c00h
int 21h

code ends
end start

每显示一个字母后,延时一段时间,让人看清,再显示下一个字母
我们可以让cpu执行一段时间的空循环,cpu执行的速度非常块,所以循环次数一定要到
用两个16位寄存器存放32位的循环次数

1
2
3
4
5
6
7
8
      mov dx,10h
mov ax,0
s: sub ax,1
sbb dx,0 ;带借位减法
cmp ax,0
jne s
cmp dx,0
jne s

上面的程序,循环1000000h次,我们可以将循环延时的程序写作一个子程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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: push ax
push dx
mov dx,1000h ;循环100000000h
mov ax,0
s1: sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret

code ends

end start

键盘输入的处理过程:
1.键盘产生扫描码
2.扫描码送入60h端口
3.引发9号中断
4.cpuz执行int9中断例程处理键盘输入

键盘输入到达60h端口后,就会引发9好中断,cpu则转去执行int 9中断例程

1.从60h端口读出键盘输入
2.调用bios的int 9中断例程,处理其他硬件细节
3.判断是否为Esc的扫描码,如果是,改变显示的颜色后返回;如果不是则直接返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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

;将原来的int 9中断例程的入口地址保存在ds:0、ds:2单元中
push es:[9*4]
pop ds:[0]
push es:[9*4+2]
pop ds:[2]

;在中断向量表中设置新的int 9中断例程的入口地址
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

mov ax,0
mov es,ax

;将中断向量表中int 9中断例程的入口恢复为原来的地址
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,10h
mov ax,0

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

int al,60h

pushf
pushf
pop bx
and bh,11111100b
push bx
popf

;对int指令进行模拟,调用原来的int9中断例程
call dword ptr ds:[0]

cmp al,1
jne int9ret

mov ax,0b800h
mov es,ax

;将属性加1,改变颜色
inc byte ptr es:[160*12+40*2+1]

int9ret: pop es
pop bx
pop ax
iret

code ends
end start

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

安装一个新的 int9 中断例程,功能:在DOS下,按下”A”键后,除非不再松开,如果松开,就显示满屏幕的”A”,其他的按键照常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
assume cs:code

stack segment
db 128 dup (0)
stack ends

code segment

start: mov ax,stack
mov ss,ax
mov sp,128

call cpy_new_int9
call sav_old_int9
call set_new_int9

testA: mov ax,1000H
jmp testA

mov ax,4c00h
int 21h

;====================================
new_int9: push ax

in al,60h
pushf
call dword ptr cs:[200h]

cmp al,9Eh
jne int9Ret
call set_screen_letter

int9Ret: pop ax
iret

;=======================================
set_screen_letter:
push bx
push cx
push dx
push es

mov bx,0b800h
mov es,bx
mov bx,0
mov dl,'A'
mov cx,2000

setScreenLetter:
mov es:[bx],dl
add bx,2
loop setScreenLetter

pop es
pop dx
pop cx
pop bx
ret

new_int9_end:
nop

;====================================
set_new_int9:
mov bx,0
mov es,bx

cli
mov word ptr es:[9*4],7E00H
mov word ptr es:[9*4+2],0
sti

ret

;====================================
sav_old_int9:
mov bx,0
mov es,bx

cli
push es:[9*4]
pop es:[200h]
push es:[9*4+2]
pop es:[202h]
sti
ret

;====================================
cpy_new_int9:
mov bx,cs
mov ds,bx
mov si,offset new_int9

mov bx,0
mov es,bx
mov di,7E00H

mov cx,offset new_int9_end - offset new_int9
cld
rep movsb

ret


;====================================

code ends

end start