王爽汇编语言第三版实验
开学三周,王爽的《汇编语言》(第三版)总算是基本上看完了,本文是总结的第二部分,包括了书本上的实验
实验1 查看CPU和内存,用机器指令和汇编指令编程
使用Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后,CPU中相关寄存器的变化。
机器码 汇编指令 执行后相关寄存器变化 b8 20 4e mov ax, 4E20H AX=4E20H 05 16 14 add ax, 1416H AX=6236H bb 00 20 mov bx, 2000H BX=2000H 01 d8 add ax, bx AX=8236H 89 c3 mov bx, ax BX=8236H 01 d8 add ax, bx AX=046CH b8 1a 00 mov ax, 001AH AX=001AH bb 26 00 mov bx, 0026H BX=0026H 00 d8 add al, bl AX=0040H 00 dc add ah, bl AX=2640H 00 c7 add bh, al BX=4026H b4 00 mov ah, 0 AX=0040H 00 d8 add al, bl AX=0066H 04 9c add al, 9CH AX=0002H
提示,可用E命令和A命令以两种方式将指令写入内存。注意用T命令执行时,CS:IP的指向。将下面3条指令写入从2000:0开始的内存单元中,利用这3条指令计算2的8次方。
1
2
3mov ax, 1
add ax, ax
jmp 2000:0003每次执行 add ax, ax 相当于将ax乘2,重复执行该条指令8次即可。
查看内存中的内容。
PC机主板上的ROM写有一个生产日期,在内存FFF00H~FFFFFH的某几个单元中,请找到这个生产日期并试图改变它。
提示,如果读者对实验的结果感到疑惑,请仔细阅读第1章中的1.15节。
通过Debug中的D命令,可以观察到生产日期以MM/DD/YY的格式存储在内存的ffff:0005-ffff:000c共计8个字节处。
该生产日期不可被修改,因为其只读。
- 向内存从B8100H开始的单元中填写数据,如:请读者先填写不同的数据,观察产生的现象;再改变填写的地址,观察产生的现象。
1
-e B810:0000 01 01 02 02 03 03 04 04
提示,如果读者对实验的结果感到疑惑,请仔细阅读第1章中的1.15节。
通过向内存中的显存地址空间写入数据,控制在屏幕上的不同位置显示不同颜色的字符。
实验2 用机器指令和汇编指令编程
使用Debug,将下面的程序段写入内存,逐条执行,根据指令执行后的实验运行情况填空。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20mov ax, ffff
mov ds, ax
mov ax, 2200
mov ss, ax
mov sp, 1000
mov ax,[0] ;ax = _____
add ax,[2] ;ax = _____
mov bx,[4] ;bx = _____
add bx,[6] ;bx = _____
push ax ;sp = _____ 修改的内存单元的地址是_____内容为_____
push bx ;sp = _____ 修改的内存单元的地址是_____内容为_____
pop ax ;sp = _____ ax = _____
pop bx ;sp = _____ bx = _____
push [4] ;sp = _____ 修改的内存单元的地址是_____内容为_____
push [6] ;sp = _____ 修改的内存单元的地址是_____内容为_____结果(不唯一):
1
2
3
4
5
6
7
8
9
10D4EA
25EE
3002
5F37
00FE 220FE 25EE
00FC 220FC 5F37
00FE 5F37
0100 25EE
00FE 220FE 3002
00FC 220FC 2F35仔细观察图3.19中的实验过程,然后分析:为什么2000:0~2000:f中的内容会发生改变?
在使用T命令进行单步追踪的时候,产生了中断,为了保护现场,CPU将PSW、CS和IP依此入栈,导致了内存相关位置内容的改变。
实验3 编程、编译、连接、跟踪
将下面的程序保存为t1.asm文件,将其生成可执行文件t1.exe。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19cs:codesg
codesg
mov ax, 2000H
mov ss, ax
mov sp, 0
add sp, 10
pop ax
pop bx
push ax
push bx
pop ax
pop bx
mov ax, 4c00h
int 21h
codesg ends
end结果:
1
2
3edit t1.asm
masm.exe t1.asm;
link.exe t1.obj;用Debug跟踪t1.exe的执行过程,写出每一步执行后,相关寄存器中的内容和栈顶的内容。
汇编指令 相关寄存器的内容 栈顶的内容 mov ax, 2000H AX = 2000H 00B8H mov ss, ax SS = 2000H _____ mov sp, 0 SP = 0 0000H add sp, 10 SP = 10 0000H pop ax AX = 0 SP = 12 0000H pop bx BX = 0 SP = 14 0000H push ax SP = 12 0000H push bx SP = 10 0000H pop ax AX = 0 SP = 12 0000H pop bx BX = 0 SP = 14 0000H mov ax, 4c00h AX = 4C00H 0000H int 21h _____ _____
结果不唯一PSP的头两个字节是CD 20,用Debug加载t1.exe,查看PSP的内容。
1
-d 2119:0
2119为CS-0010H
实验4 [bx]和loop的使用
编程,向内存0:200~0:23F依此传送数据0~63(3FH)。
编程,向内存0:200~0:23F依此传送数据0~63(3FH),程序中只能使用9条指令,9条指令中包括“mov ax, 4c00h”和“int 21h”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15cs:code
code
mov ax, 0020h
mov ds, ax
mov bx, 0
mov cx, 64
s: mov [bx], bl
inc bl
loop s
mov ax, 4c00h
int 21h
code ends
end下面的程序的功能是将“mov ax, 4c00h”之前的指令复制到内存的0:200处,补全程序,上机调试,跟踪运行结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16cs:code
code
mov ax, _____
mov ds, ax
mov ax, 0020h
mov es, ax
mov bx, 0
mov cx, _____
s: mov al, [bx]
mov es:[bx], al
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end结果:
1
2code
18H提示:
复制的是什么?从哪里到哪里?
复制的是代码段中mov ax, 4c00h之前的代码,以数据的形式,从内存中代码段的位置复制到内存中0:200处开始的一段连续的空间。
复制的是什么?有多少个字节?你如何直到要复制的字节的数量?
可以用offset计算得出,也可以在Debug中用T命令观察得出。
实验5 编写、调试具有多个段的程序
将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
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
28cs:code, ds:data, ss:stack
data
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data ends
stack
dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends
code
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax, 4c00h
int 21h
code ends
end start①CPU执行程序,程序返回前,data段中的数据为多少?
②CPU执行程序,程序返回前,CS = _____、SS = _____、DS = _____。
③设程序加载后,code段的段地址为X,则data段的段地址为_____,stack段的段地址为_____。
答案:
①data段中的数据不变。
②212B、212A、2129(答案不唯一)
③X-2、X-1将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
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
28cs:code, ds:data, ss:stack
data
dw 0123h, 0456h
data ends
stack
dw 0, 0
stack ends
code
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax, 4c00h
int 21h
code ends
end start(1)CPU执行程序,程序返回前,data段中的数据为多少?
(2)CPU执行程序,程序返回前,CS = _____、SS = _____、DS = _____。
(3)设程序加载后,code段的段地址为X,则data段的段地址为_____,stack段的段地址为_____。
(4)对于如下定义的段:1
2
3name
...
ends如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为_____。
答案:
(1)data段中的数据不变。
(2)212B、212A、2129(答案不唯一)
(3)X-2、X-1
(4)((N-1)/16 + 1)*16 其中除法为整除将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
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
28cs:code, ds:data, ss:stack
code
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
push ds:[0]
push ds:[2]
pop ds:[2]
pop ds:[0]
mov ax, 4c00h
int 21h
code ends
data
dw 0123h, 0456h
data ends
stack
dw 0, 0
stack ends
end start(1)CPU执行程序,程序返回前,data段中的数据为多少?
(2)CPU执行程序,程序返回前,CS = _____、SS = _____、DS = _____。
(3)设程序加载后,code段的段地址为X,则data段的段地址为_____,stack段的段地址为_____。
答案:
(1)data段中的数据不变。
(2)2129、212D、212C(答案不唯一)
(3)X+3、X+4如果将1. 2. 3.题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
答案:
只有程序3可以正确运行,在不指明程序入口的情况下,程序默认按照顺序从头开始执行,而3个程序中只有程序3的code段位于最开始的部分,所以只有程序3可以正确运行。程序如下,编写code段中的代码,将a段和b段中的数据依此相加,将结果存到c段中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18cs:code
a
db 1, 2, 3, 4, 5, 6, 7, 8
a ends
b
db 1, 2, 3, 4, 5, 6, 7, 8
b ends
c
db 0, 0, 0, 0, 0, 0, 0, 0
c ends
code
start:
?
code ends
end start答案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15start: mov ax, a
mov ds, ax
mov ax, b
mov es, ax
mov ax, c
mov ss, ax
mov bx, 0
mov cx, 8
s: mov al, [bx]
add al, es:[bx]
mov ss:[bx], al
inc bx
loop s
mov ax, 4c00h
int 21h程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16cs:code
a
dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 0ah, 0bh, 0ch, 0dh, 0eh, 0fh, 0ffh
a ends
b
dw 0, 0, 0, 0, 0, 0, 0, 0
b ends
code
start:
?
code ends
end start答案:
1
2
3
4
5
6
7
8
9
10
11
12start: mov ax, b
mov ss, ax
mov sp, 16
mov ax, a
mov ds, ax
mov bx, 0
mov cx, 8
s: push [bx]
add bx, 2
loop s
mov ax, 4c00h
int 21h
实验6 实践课程中的程序
将课程中所有讲解过的程序上机调试,用Debug跟踪其执行过程,并在过程中进一步理解所讲内容。
编程,完成问题7.9中的程序。
程序如下: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
35cs:codesg, ss:stacksg, ds:datasg
stacksg
dw 0, 0, 0, 0, 0, 0, 0, 0
stacksg ends
datasg
db '1. display '
db '2. brows '
db '3. replace '
db '4. modify '
datasg ends
codesg
start: mov ax, datasg
mov ds, ax
mov ax, stacksg
mov ss, ax
mov sp, 16
mov bx, 0
mov cx, 4
s: push cx
mov cx, 4
mov si, 0
s0: mov al, [bx + si + 3]
and al, 11011111b
mov [bx + si + 3], al
inc si
loop s0
add bx, 16
pop cx
loop s
mov ax, 4c00h
int 21h
codesg ends
end start
实验7 寻址方式在结构化数据访问中的应用
编程,将data段中的数据按如下格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中。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
73cs:codesg, ss:stack
stack
dw 8 dup (0)
stack ends
data
db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983'
db '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992'
db '1993', '1994', '1995'
dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
data ends
table
db 21 dup ('year summ ne ?? ')
table ends
codesg
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, table
mov ds, ax
mov ax, data
mov es, ax
mov bx, 0
mov si, 0
mov cx, 21
year: push cx
mov cx, 4
mov di, 0
char: mov al, es:[si]
mov [bx+di], al
inc si
inc di
loop char
add bx, 16
pop cx
loop year
mov cx, 21
mov bx, 0
income: mov ax, es:[si]
mov [5+bx], ax
add si, 2
mov ax, es:[si]
mov [7+bx], ax
add si, 2
add bx, 16
loop income
mov cx, 21
mov bx, 0
staff: mov ax, es:[si]
mov [10+bx], ax
add si, 2
add bx, 16
loop staff
mov cx, 21
mov bx, 0
average:mov ax, [bx+5]
mov dx, [bx+7]
div word ptr [bx+10]
mov [13+bx], ax
add bx, 16
loop average
mov ax, 4c00h
int 21h
codesg ends
end start
实验8 分析一个奇怪的程序
分析下面的程序,在运行前思考,这个程序可以正确返回吗?
运行后再思考:为什么是这种结果?
通过这个程序加深对相关内容的理解。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19cs:codesg
codesg
mov ax, 4c00h
int 21h
start: mov ax, 0
s: nop
nop
mov di, offset s
mov si, offset s2
mov ax, cs:[si]
mov cs:[di], ax
s0: jmp short s
s1: mov ax, 0
int 21h
mov ax, 0
s2: jmp short s1
nop
codesg ends
end start
分析:
这个程序可以正确返回,程序的入口为mov ax, 0,注意到指令jmp short s1占2字节,于是指令mov di, offset s将s的偏移地址传送到寄存器DI,mov si, offset s2将s2的偏移地址传送到SI,然后再通过通用寄存器ax做中转将s2处的指令复制到s处,最后再跳转至s处执行复制过来的指令。
注意jmp short s1是相对跳转,其直接修改IP寄存器,从s2到s1共有8个字节的偏移,实际上 jmp short s1等价于(ip)=(ip)-8,通过Debug可知第一个nop指令的偏移地址为8,所以再执行了复制过的指令后,IP将指向0,程序按照顺序执行mov ax, 4c00h和int 21h,正确返回。
实验9 根据材料编程
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串’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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46ds:data, cs:code
data
db 'welcome to masm!'
data ends
code
start: mov ax, data
mov ds, ax
mov ax, 0B800H
mov es, ax
mov bx, 1664
mov si, 0
mov cx, 16
char1: mov al, [si]
mov ah, 10000010B
mov es:[bx], ax
add bx, 2
inc si
loop char1
mov bx, 1824
mov si, 0
mov cx, 16
char2: mov al, [si]
mov ah, 10100100B
mov es:[bx], ax
add bx, 2
inc si
loop char2
mov bx, 1984
mov si, 0
mov cx, 16
char3: mov al, [si]
mov ah, 11110001B
mov es:[bx], ax
add bx, 2
inc si
loop char3
mov ax, 4C00H
int 21H
code ends
end start
实验10 编写子程序
显示字符串
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
62cs:code, ss:stack
stack
dw 16 dup (0)
stack ends
data
db 'Welcome to masm!', 0
data ends
code
start: mov dh, 8
mov dl, 3
mov cl, 2
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 32
mov si, 0
call show_str
mov ax, 4c00h
int 21h
show_str:
push cx
push bx
push ax
push si
push di
push es
;using cx, bx, ax, si, di, es
mov ax, 0b800h
mov es, ax
mov bx, 0
mov di, 0
mov al, 160
mul dh
add bx, ax
mov al, 2
mul dl
add bx, ax ;bx stores address of start character
mov al, cl ;al stores the color of character
char: mov ch, 0
mov cl, ds:[si]
jcxz
mov ch, al
mov es:[bx+di], cx
add di, 2
inc si
jmp char
zero: pop es
pop di
pop si
pop ax
pop bx
pop cx
ret
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
35cs:code, ss:stack
stack
dw 16 dup (0)
stack ends
code
start: mov ax, stack
mov ss, ax
mov sp, 32
mov ax, 4240h
mov dx, 000fh
mov cx, 0ah
call divdw
mov ax, 4c00h
int 21h
divdw: push bx
mov bx, ax ; bx stores L
mov ax, dx ; ax stores H
mov dx, 0
div cx ; after div, ax holds int(H/N), dx holds rem(H/N)
push ax ; push int(H/N) temporarily
mov ax, bx ; ax stores L
div cx
mov cx, dx
pop dx
pop bx
ret
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
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
97cs:code, ss:stack
stack
dw 16 dup (0)
stack ends
data
db 10 dup (0)
data ends
code
start: mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 32
mov ax, 12666
mov si, 0
call dtoc
mov dh, 8
mov dl, 3
mov cl, 2
call show_str
mov ax, 4c00h
int 21h
dtoc: push ax
push si
push di
push dx
push bx
push cx
mov di, 0
mov dx, 0
mov bx, 10
devide: mov cx, ax
jcxz stop
div bx
inc di
push dx
mov dx, 0
jmp devide
stop: mov cx, di
string: pop bx
add bx, 30h
mov [si], bl
inc si
loop string
pop cx
pop bx
pop dx
pop di
pop si
pop ax
ret
show_str:
push cx
push bx
push ax
push si
push di
push es
;using cx, bx, ax, si, di, es
mov ax, 0b800h
mov es, ax
mov bx, 0
mov di, 0
mov al, 160
mul dh
add bx, ax
mov al, 2
mul dl
add bx, ax ;bx stores address of start character
mov al, cl ;al stores the color of character
char: mov ch, 0
mov cl, ds:[si]
jcxz
mov ch, al
mov es:[bx+di], cx
add di, 2
inc si
jmp char
zero: pop es
pop di
pop si
pop ax
pop bx
pop cx
ret
code ends
end start
实验11 编写子程序
1 | cs:code |
实验12 编写0号中断的处理程序
1 | cs:code |
实验13 编写、应用中断例程
编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。
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
63cs:code
code
start: mov ax, cs
mov ds, ax
mov si, offset print
mov ax, 0
mov es, ax
mov di, 200h
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 es
push ax
push cx
push dx
push si
push di
mov ax, 0b800h
mov es, ax
mov al, 160
mov ah, 0
mul dh
mov di, ax
add dl, dl
mov dh, 0
add di, dx
mov al, cl
printstart:
mov ch, 0
mov cl, [si]
jcxz
mov ch, al
mov es:[di], cx
add di, 2
inc si
jmp printstart
zero:
pop di
pop si
pop dx
pop cx
pop ax
pop es
iret
printend:
nop
code ends
end start编写并安装int 7ch中断例程,功能为完成loop指令功能。
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
32cs:code
code
start: mov ax, cs
mov ds, ax
mov si, offset lp
mov ax, 0
mov es, ax
mov di, 200h
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
jcxz lpret
add [bp + 2], bx
lpret: pop bp
iret
lpend: nop
code ends
end start下面的程序,分别在屏幕的第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
30cs:code
code
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[si]
[bx]
add bx, 2
inc si
实验14 访问CMOS RAM
编程,以”年/月/日 时:分:秒”的格式,显示当前的日期,时间。
注意:CMOS RAM中存储着系统的配置信息,出了保存时间信息的单元外,不要向其他的单元中写入内容,否则将引起一些系统错误。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
58cs:code, ds:data
data
s db 9, 8, 7, 4, 2, 0
data ends
code
start: mov ax, 0b800h
mov es, ax
mov di, 160 * 12
mov ax, data
mov ds, ax
mov si, 0
mov cx, 6
print: mov al, s[si]
out 70h, al
in al, 71h
call number
cmp si, 2
jb slash
je space
cmp si, 5
jb colon
next: inc si
loop print
mov ax, 4c00h
int 21h
;al->number, es:di->begin
number: push cx
mov ah, al
mov cl, 4
shr ah, cl
and al, 00001111b
add ah, 30h
add al, 30h
mov byte ptr es:[di], ah
mov byte ptr es:[di + 2], al
add di, 4
pop cx
ret
slash: mov byte ptr es:[di], '\'
add di, 2
jmp next
colon: mov byte ptr es:[di], ':'
add di, 2
jmp next
space: mov byte ptr es:[di], ' '
add di, 2
jmp next
code ends
end start
实验15 安装新的int 9中断例程
安装一个新的int 9中断例程,功能:在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
67cs:code
stack
db 128 dup (0)
stack ends
code
start: mov ax, stack
mov ss, ax
mov sp, 128
push cs
pop ds
mov ax, 0
mov es, ax
mov si, offset int9
mov di, 204h
mov cx, offset int9end - offset int9
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 word ptr cs:[200h]
cmp al, 9eh
jne int9ret
mov ax, 0b800h
mov es, ax
mov bx, 0
mov cx, 2000
s: mov byte ptr es:[bx], 'A'
add bx, 2
loop s
int9ret:pop es
pop cx
pop bx
pop ax
iret
int9end:nop
code ends
end start
实验16 编写包含多个功能子程序的中断例程
安装一个新的int 7ch中断例程,为显示输出提供如下功能子程序
- 清屏
- 设置前景色
- 设置背景色
- 向上滚动一行
1 | cs:code |
参考王爽《汇编语言》实验16:包含多个功能子程序的中断例程 解答
可以用伪指令org x简化该程序
org x表明接下来的指令从偏移地址x开始
修改后的相关指令如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14org 200h
screen: jmp short set
table dw sub1, sub2, sub3, sub4
set: push bx
cmp ah, 3
ja sret
mov bl, ah
mov bh, 0
add bx, bx
call word ptr table[bx]
实验17 编写包含多个功能子程序的中断例程
安装一个新的int 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
50
51
52
53
54cs:code
code
start: mov ax, cs
mov ds, ax
mov si, offset floppyio
mov ax, 0
mov es, ax
mov di, 200h
mov cx, offset floppyioend - offset floppyio
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
floppyio:
push ax
push cx
push dx
add ah, 2
mov al, 1
push ax ;计算相应的ah和al并压栈
mov ax, dx
mov dx, 0
mov cx, 1440
div cx ;计算逻辑扇区号/1440
push ax ;将商即面号压栈
mov ax, dx
mov dl, 18
div dl ;计算逻辑扇区号/1440的余数/18
inc ah
mov ch, al
mov cl, ah ;设置相应的ch和cl
pop ax ;将相应的面号出栈
mov dh, al
mov dl, 0 ;设置相应的dh和dl
pop ax ;将相应的ah和al出栈
int 13h ;调用13h例程进行实际的读写
pop dx
pop cx
pop ax
iret
floppyioend:
nop
code ends
end start