0%

《汇编语言》(第四版) 实验 13

《汇编语言(第四版)》 . 王爽著 . 清华大学出版社 . 2019

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

一些例程与检测点

使用 int 指令调用中断处理程序

可以在程序中使用 int 指令调用任何一个中断的中断处理程序

在下面的程序中,CPU 执行 int 0 指令时,将引发中断过程,执行 0 号中断处理程序

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

code segment
start: mov ax,0b800h
mov es,ax
mov byte ptr es:[12*160+40*2],'!'
int 0

code ends

end start
测试程序运行

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

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

code segment
start: mov ax,3456 ;(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,0200h ;设置 es:di 指向目的地址

mov cx,offset sqrend-offset sqr ;设置 cx 为传输长度

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 ;7ch 中断处理程序
iret ;iret : pop IP pop CS popf

sqrend: nop

code ends
end start

在执行完中断例程后,应该用 iret 指令恢复 int 7ch 执行前的标志寄存器和 CS、IP 的值

int 指令和 iret 指令的配合使用与 call 指令和 ret 指令的配合使用具有相似的思路

用 Debug 跟踪程序运行

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

安装程序如下

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
assume cs:code
code segment
start: ;串传送操作
mov ax,cs
mov ds,ax
mov si,offset capital
mov ax,0
mov es,ax
mov di,0200h

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: ;保存用到的寄存器
push cx
push si

;处理中断
change: mov cl,ds:[si]
mov ch,0
jcxz ok
and byte ptr [si],11011111b
inc si
jmp short change

ok: ;恢复用到的寄存器
pop si
pop cx
;用 iret 指令返回
iret

capitalend: nop

code ends
end start
用 Debug 跟踪程序运行


安装中断例程的程序的基本框架

1)主程序
串传送操作:
      设置 ds:si 指向源地址
      设置 es:di 指向目的地址
      设置 cx 为传输长度
      设置传输方向
      进行串传送
设置中断向量表:
      将中断例程的入口地址写入相应表项
程序返回;

2)子程序
中断处理函数:
      保存用到的寄存器
      处理中断
      恢复用到的寄存器
      用 iret 指令返回

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

loop s 的执行需要两个信息,循环次数和到 s 的位移,7ch 中断例程也需要以这两个变量为参数,用 cx 存放循环次数,用 bx 存放位移。

应用举例:在屏幕中间显示 80 个 “!”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
assume cs:code
code segment
start: mov ax,0b800h
mov es,ax
mov di,160*12 ;屏幕缓冲区中央

mov bx,offset s-offset se ;设置从标号 se 到标号 s 的转移位移
mov cx,80 ;设置循环次数
s: mov byte ptr es:[di],'!'
add di,2
int 7ch ;如果 (cx)≠0,转移到标号 s 处
se: nop

mov ax,4c00h
int 21h
code ends
end start

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

  1. dec cx;
  2. 如果 (cx)≠0,转到标号 s 处执行,否则向下执行。

通过 se 的偏移地址加上 bx 中存放的转移位移得到 s 的偏移地址
通过改变栈中被压栈的 IP 的内容,再使用 iret 指令,从而真正改变 IP,使 CS:IP 转移到标号 s 处

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
code segment
start: mov ax,cs
mov ds,ax
mov si,offset lp
mov ax,0
mov es,ax
mov di,0200h
mov cx,offset lpend-offset lp
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

lp: push bp
mov bp,sp
dec cx ;cx 递减
jcxz lpret ;(cx)=0 时跳出循环
add [bp+2],bx ;通过修改压入栈中的 IP 数据,实现弹出后转移到标号 s 处
lpret: pop bp
iret
lpend: nop

code ends
end start
测试程序运行

检测点 13.1

(1)-32768~32767

实际上 loop 指令为短转移,对 IP 的修改范围为 -128 ~ 127

(2)应用程序:

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
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,[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

安装程序如下

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 print
mov ax,0
mov es,ax
mov di,0200h
mov cx,offset printend-offset print
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

print: push bp
mov bp,sp
add [bp+2],bx
pop bp
iret
printend: nop

code ends
end start
测试程序运行

检测点 13.2

(1)错误,内存区域只读。

(2)int 19h 在 DOS 启用之前调用,由 BIOS 提供。

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

BIOS 中断例程应用

BIOS 和 DOS 提供的中断例程,用 ah 来传递内部子程序的编号。

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

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

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

mov ax,4c00h
int 21h

code ends
end
测试程序运行

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

DOS 中断例程应用

DOS 为程序员提供了许多可以调用的子程序,都包含在 int 21h 中断例程中
int 21h 中断例程的 4ch 号功能,即程序返回功能

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

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

code segment
start: mov ah,2 ;置光标
mov bh,0 ;第 0 页
mov dh,5 ;dh 中放行号
mov dl,12 ;dl 中放列号
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)(2)在之前的程序中都有所体现,这里只将没有与之前完全重复的实验任务(1)再做一遍

实验任务(1)


应用程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assume cs:code
data segment
db "welcome to masm! ",0
data ends
code segment
start: mov dh,10 ;行号
mov dl,10 ;列号
mov cl,2 ;颜色
mov ax,data
mov ds,ax
mov si,0 ;字符串首地址
int 7ch
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset print
mov ax,0
mov es,ax
mov di,0200h
mov cx,offset printend-offset print
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

print: push ax
push bx
push cx
push dx
push si
push di
push es

mov bl,dl ;处理列
mov bh,0
add bx,bx

mov al,dh ;处理行
mov ah,160
mul ah
mov di,ax

mov ax,0b800h
mov es,ax

mov ah,2
s: mov al,ds:[si]
cmp byte ptr ds:[si],0
je ok
mov es:[di+bx],ax
inc si
add bx,2
jmp short s
ok: pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
printend: nop

code ends
end start
测试程序运行


实验任务(2)


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

实验任务(3)

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
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 ;第 0 页
mov dh,ds:[si] ;dh 中放行号
mov dl,0 ;dl 中放列号
mov ah,2 ;置光标
int 10h

mov dx,ds:[bx]
mov ah,9 ;第 21h 号中断例程的 9 号子程序
int 21h ;显示字符串
inc si
add bx,2
loop ok

mov ax,4c00h
int 21h
code ends
end start
测试程序运行


汇编语言实验合集

汇编语言实验合集

实验 1 查看 CPU 和内存,用机器指令和汇编指令编程
实验 2 用机器指令和汇编指令编程
实验 3 编程、编译、连接、跟踪
实验 4 [bx] 和 loop 的使用
实验 5 编写、调试具有多个段的程序
实验 6 实践课程中的程序
实验 7 寻址方式在结构化数据访问中的应用
实验 8 分析一个奇怪的程序
实验 9 根据材料编程
实验 10 编写子程序
课程设计 1
实验 11 编写子程序
实验 12 编写 0 号中断的处理程序
实验 13 编写、应用中断例程
实验 14 访问 CMOS RAM
实验 15 安装新的 int9 中断例程
实验 16 编写包含多个功能子程序的中断例程
实验 17 编写包含多个功能子程序的中断例程
课程设计 2