蒙珣的博客

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

0%

实验13 编写、应用中断例程

编写、安装中断7ch的中断例程
功能:求word型数据的平方
参数:(ax)=要计算的数据
返回值:dx、ax中存放结果的高16位和低16位
应用举例:求2*3456^2

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

code segment

start: mov ax,3456
int 7ch ;调用中断7ch的中断例程,计算ax中的数据的平方
add ax,ax
adc dx,dx ;dx:ax存放结果,将结果乘以2
mov ax,4c00h
int 21h

code ends

end start

1)实现求平方的功能的程序
2)安装程序,将其安装在0:200处
3)设置中断向量表,将程序的入口地址保存在7ch表项中,使其成为中断7ch的中断例程

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
assume cs:code

code segment

start: mov ax,cs
mov ds,ax
mov si,offset sqr ;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置es:di指向目的地址
mov cx,offset sqrend - offset sqr
cld
rep movsb

mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0

mov ax,4c00h
int 21h

sqr: mul ax
iret

sqrend: nop

code ends

end start

编写、安装中断7ch的中断例程

功能:将一个全是字母,以0结尾的字符串,转化为大写
参数:ds:si指向字符串的首地址

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

data segment
db 'conversation',0
data ends

code segment

start: mov ax,data
mov ds,ax
mov si,0
int 7ch

mov ax,4c00h
int 21h

code ends

end start

实现小写转换为大写的功能
安装程序,将其安装在0:200处
设置中断向量表,将程序入口地址保存在7ch表项中

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
assume cs:code

data segment
db 'conversation',0
data ends

code segment

start: mov ax,cs
mov ds,ax
mov si,offset capital
mov ax,0
mov es,ax
mov di,200h
mov cx,offset capitalend - offset capital
cld
rep movsb

mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov ax,4c00h
int 21h

capital: jmp short change
db 'conversation',0
push cx
push si

change: mov cl,ds:[si]
mov ch,0
jcxz ok
and byte ptr ds:[si],11011111b
inc si
jmp change

ok: pop si
pop cx
iret

capitalend: nop

mov ax,4c00h
int 21h

code ends

end start

用7ch中断例程完成 loop指令的功能

loop s的执行需要两个信息,循环次数和到s的位移,所以,7ch中断例程需要完成loop指令的功能,也需要这两个信息作参数

我们需要cx存放循环次数,用bx存放位移

应用举例:在屏幕中间显示80个’!’

程序框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assume cs:code

code segment

start: mov ax,0b800h
mov es,ax
mov di,160*2

mov bx,offset s - offset se ;设置从标号se到标号s的转移位移
mov cx,80

s: mov byte ptr es:[di],'!'
add di,2
int 7ch

se: nop

mov ax,4c00h
int 21h

code ends

end start

分析,为了模拟loop指令,7ch中断例程应具备下面的功能

  1. dec cx
  2. 如果cx不为0,跳转到s处,否则向下执行

7ch 中断例程如下

1
2
3
4
5
6
7
8
lp:     push bp
mov bp,sp
dec cx
jcxz ipret
add [bp+2],bx

ipret: pop bp
iret

用7ch中断例程完成jmp near ptr s指令的功能,用bx向中断例程传送转移位移

应用举例:在屏幕的第12行,显示data段中以0结尾的字符串

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
assume cs:code

data segment
db 'conversation',0
data ends

code segment

start: mov ax,data
mov ds,ax
mov si,0

mov ax,0b800h
mov es,ax
mov di,12*160

s: cmp byte ptr [si],0
je ok ;如果是0跳出循环
mov al,ds:[si]
mov es:[di],al
inc si
add di,2
mov bx,offset s - offset ok ;设置从标号ok到标号s的转移位移
int 7ch ;转移到标号s处

ok: mov ax,4c00h
int 21h

code ends

end start

7ch中断例程

1
2
3
4
5
jnp:        push bp
mov bp,sp
add [bp+2],bx
pop bp
iret

int 10h 中断例程得设置光标位置功能

mov ah,2 ;设置光标
mov bh,0 ;第0页
mov dh,5 ;dh中放行号
mov dl,12 ;dl中放行号
int 10

ah=2表示调用第10h号中断例程得2号子程序,功能为设置光标位置
bh=0设置光标到0页
dh=5设置光标到第5行
dl=12设置光标到第12列

int 10h 中断例程在光标位置显示字符功能

mov ah,9 ;光标位置显示字符
mov al,’a’ ;字符
mov bl,7 ;颜色属性
mov bh,0 ;第0页
mov cx,3 ;字符重复个数
int 10h

ah=9表示调用第10h号中断例程第2号子程序,功能为设置光标位置显示字符
可以提供显示字符、颜色属性、页号、字符重复个数作为参数
bl中颜色属性得格式如下:
7 6 5 4 3 2 1 0
BL R G B I R G B
闪烁 背景 高亮 前景

编程:在屏幕的5行12列显示3个红底高亮闪烁绿色的’a‘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
assume cs:code
code segment

start: mov ah,2 ;设置光标
mov bh,0 ;第0页
mov dh,5 ;设置光标第5行
mov dl,12 ;设置光标第12列
int 10h


mov ah,9 ;在光标位置显示字符
mov al,'a' ;字符
mov bl,11001010b;颜色属性
mov bh,0 ;第0页
mov cx,3 ;字符重复3个
int 10h

mov ax,4c00h
int 21h

code ends
end start

int 21h 中断例程的4ch号功能,即程序返回功能

mov ah,4ch ;程序返回
mov al,0 ;返回值
int 21h

ah=4ch 表示调用第21h号中断例程的4ch号子程序,功能为程序返回,可以提供返回值作为参数
我们前面使用这个功能的时候经常写作:

mov ax,4c00h
int 21h

我们看一下 int 21h中断例程在光标位置显示字符串的功能

ds:dx 指向字符串 ;要显示的字符串需用”$“作为结束符
mov ah,9 ;功能号9,表示在光标位置显示字符串
int 21h

ah=9表示调用第21h号中断例程的9号子程序,功能为在光标位置显示字符串,可以提供要显示字符串的地址作为参数

编程:在屏幕的5行12列显示字符串”Welcome to masm!“

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
assume cs:code
code segment

data segment
db 'Welcome to masm!','$'
data ends

start: mov al,2 ;设置光标位置
mov bh,0 ;第0页
mov dh,5 ;第5行
mov dl,12 ;第12列
int 10h

mov ah,9 ;在光标显示字符
mov bl,11001010b;颜色属性
mov bh,0 ;第0页
mov cx,16 ;字符重复16个
int 10h

mov ax,data ;设置光标显示字符
mov ds,ax
mov dx,0 ;ds:dx 指向字符串的首地址data:0
mov ah,9
int 21h

mov ax,4c00h
int 21h

code ends
end start

实验1:

编写、安装 int 7ch 中断程序,功能为显示一个用0结束的字符串,中断程序安装在0:7E00

参数:dh = 行号
dl = 列号
cl = 颜色
ds:si 指向字符串首地址

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
assume cs:code,ds:data,ss:stack


data segment
db 'welcome to masm!',0
data ends

stack segment stack
db 128 dup (0)
stack ends

code segment

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

call int7ch ;安装程序
call set_int7ch ;登记在中断项链表中

call init_reg ;初始化显示字符串
call show_masm ;显示字符串

mov ax,4c00h
int 21h

;初始化显示字符串
;===============================
init_reg: mov bx,data
mov ds,bx

mov bx,0B800H
mov es,bx
ret

;显示在哪里
;===============================
show_masm: mov si,0
mov dh,15 ;行号
mov dl,20 ;列号
mov cl,2 ;颜色

int 7ch

ret

;===============================
new_int7ch: call get_row
call get_col
call show_string

iret

new_int7ch_end: nop

;显示字符串
;===============================
show_string:push dx
push ds
push es
push si
push di

mov dh,cl

showSting: mov dl,ds:[si]
cmp dl,0
je showStringRet
mov es:[di],dx
add di,2
inc si
jmp showString

showStringRet:
pop di
pop si
pop es
pop ds
pop dx
ret

;设置显示的行
;===============================
get_row: mov al,160
mul dh

mov di,ax
ret

;设置显示的列
;===============================
get_col: mov al,2
mul dl

mov di,ax
ret


;登记中断向量表
;===============================
set_int7ch: mov bx,0
mov es,bx

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

ret

;安装程序
;===============================
int7ch: mov bx,cs
mov ds,bx
mov si,offset new_int7ch

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

mov cx,offset new_int7ch - offset new_int7ch_end
cld
rep movsb
ret

code ends
end start

实验2:编写并安装 int 7ch 中断例程,功能为完成loop指令的例程

参数:cx = 循环次数 bx = 位移

在屏幕中间显示80个!

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
assume cs:code,ds:data,ss:stack

data segment
db 128 dup (0)
data ends

stack segment
db 128 dup (0)
stack ends

code segment

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

call int7ch
call set_int7ch

call init_reg
call show_char

mov ax,4c00h
int 21h

;=================================
show_char: mov cx,80

mov di,160*12

mov bx,offset showChar - offset showCharRet

showChar: mov byte ptr es:[di],'!'
add di,2
int 7ch ;loop cx = cx - 1

showCharRet: ret

;=================================
init_reg: mov bx,0B800H
mov es,bx

ret

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

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

ret

;=================================
new_int7ch: push bp ;bp ip cs pushf
mov bp,sp
dec cx
jcxz new_int7ch_end
add ss:[bp+2],bx

int7chRet: pop bp
iret

new_int7ch_end: nop

;=================================
int7ch: mov bx,cs
mov ds,bx
mov si,offset new_int7ch

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

mov cx,offset new_int7ch_end - offset new_int7ch
cld
rep movsb
ret

code ends

end startassume cs:code

data segment
db 128 dup (0)
data ends

stack segment
db 128 dup (0)
stack

code segment

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

call int7ch
call set_int7ch

call init_reg
call show_char

mov ax,4c00h
int 21h

;=================================
show_char: mov cx,80

mov di,160*12

mov bx,offset showCharRet - offset showChar

showChar: mov byte ptr es:[di],'!'
add di,2
int 7ch ;loop cx = cx - 1

showCharRet: ret

;=================================
init_reg: mov bx,0B800H
mov es,bx

ret

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

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

ret

;=================================
new_int7ch: push bp ;bp ip cs pushf
mov bp,sp
dec cx
jcxz new_int7ch_end
add ss:[bp+2],bx

new_int7ch_end: pop bp
iret

;=================================
int7ch: mov bx,cs
mov ds,bx
mov si,offset new_int7ch

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

mov cx,offset new_int7ch_end - offset new_int7ch
cld
rep movsb
ret

code ends

ends start

实验3 下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全程序

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
assume cs:code

code segment
s1: db 'Good,better,best,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s: dw offset s1,offset s2,offset s3,offset s4
row:db 2,4,6,8

start: mov ax,cs
mov ds,ax
mov bx,offset s
mov si,offset row
mov cx,4

ok: mov bh,0
mov dh,_____
mov dl,0
mov ah,2
int 10h

mov dx,____
mov ah,9
int 21h
__________
__________
loop ok

mov ax,4c00h
int 21h

code ends
end start

补全后的程序

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
assume cs:code

code segment
s1: db 'Good,better,best,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'

s: dw offset s1, ;bx+0
offset s2, ;bx+2
offset s3, ;bx+4
offset s4 ;bx+6

row:db 2,4,6,8

start: mov ax,cs
mov ds,ax ;将ds指向cs段
mov bx,offset s ;bx=s标号地址
mov si,offset row ;si=row标号地址
mov cx,4 ;计数器设置为4,有4行字符串

ok: mov bh,0 ;第0页
; mov dh,____
mov dh,ds:[si] ;行号
mov dl,0 ;列号
mov ah,2 ;调用10h号中断程序第2号子程序,设置光标位置
int 10h

; mov dx,____
mov dx,ds:[bx] ;dx=ds:[bx],每个字符首地址
mov ah,9 ;dos系统21h例程9号子程序
int 21h

inc si ;si按字节定义,每次增量为1
add bx,2
; __________
; __________
loop ok

mov ax,4c00h
int 21h

code ends
end start