项目情景
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串”welcome to masm!”
分析
情景要求以及需要实现的功能非常简单,这里分析一下其中的几个要点:
- 字符串
"welcome to masm!"
,查表可得其ASCII编码,不过也可以直接写到data
段里,打印时再取用,将ASCII编码写入显示的字符所在字的低位字节即可; - 中间,也即屏幕正中间,我们要打印的字符串长度为16,共打印3次,对于80x25(字符)的DOS屏幕,如果要显示在正中间,第1行应显示在第12行(偏移地址为
780H
)处,每行第1个字符应显示在该行的第32列处(偏移地址为40H
),换行可以通过偏移地址+0A0H
实现,因为每行显示80个字符,每个字符占2字节; - 绿色、绿底红色、白底蓝色,可以通过调节属性字节实现更改,属性字节的格式如下:绿色的属性字节为:
1
2
37 6 5 4 3 2 1 0
BL R G B I R G B
0-2为前景色,3为高亮,4-6为背景色,7为闪烁0000 0010B
,即02H
;
绿底红色的属性字节为:0010 0100B
,即24H
;
白底蓝色的属性字节为:0111 0001B
,即71H
;
将对应的属性字节写入显示的字符所在字的高位字节即可;
程序实现
指定各段的段寄存器:1
assume cs:code,ds:data
定义数据段data
,向其中写入需要打印的字符串welcome to masm!
:1
2
3
4data segment
db "w e l c o m e t o m a s m ! "
; 需要被打印的字符串
data ends
每个字符后面都加了一个空格,是为了以字的形式写入字符串,确保与显存中的位置拥有相同的偏移地址;
定义代码段code
和程序起始点start
:1
2
3
4
5code segment
start:
......
code ends
end start
由于没有需要暂存的数据(比如循环变量),所以这次的程序中不需要栈段;
初始化各段寄存器,使ds
指向data
,es
指向显存:1
2
3
4
5mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
以第一行为例,简单看看打印文本的代码:1
2
3
4
5
6
7
8
9
10
11
12
13; 第1行
; 背景:黑
; 前景:绿
mov bx,0
mov si,780h ; 设置第1行的偏移地址
mov cx,16 ; 16个字符,循环16次
s:
mov al,ds:[bx]
mov ah,02h ; 将ASCII码与属性字节02H拼接形成显存中的字
mov es:[bx+si+40h],ax ; 写入显存对应位置,因为每行第1个字符在第32列所以要+40H
add bx,2
inc di
loop s
换行就si+0A0H
:1
add si,0a0h
其他两行也是同理,此处就不再赘述了;
(本来想用一个循环的,但是每行需要写入的属性字节不同,只得作罢)
最后返回:1
2mov ax,4c00h
int 21h
完整的程序如下: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; hello.asm
assume cs:code,ds:data
data segment
db "w e l c o m e t o m a s m ! "
; The strings to be printed
data ends
code segment
start:
; segReg init
mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
; 1st line
; bg:black
; fg:green
mov bx,0
mov si,780h
mov cx,16
s:
mov al,ds:[bx]
mov ah,02h
mov es:[bx+si+40h],ax
add bx,2
inc di
loop s
; 2nd line
; bg:green
; fg:red
mov bx,0
add si,0a0h
mov cx,16
s1:
mov al,ds:[bx]
mov ah,24h
mov es:[bx+si+40h],ax
add bx,2
inc di
loop s1
; 3rd line
; bg:white
; fg:blue
mov bx,0
add si,0a0h
mov cx,16
s2:
mov al,ds:[bx]
mov ah,71h
mov es:[bx+si+40h],ax
add bx,2
inc di
loop s2
; Termination
mov ax,4c00h
int 21h
code ends
end start
感觉写得很烂,但似乎也没有更好的实现方法了(
运行结果
编译、链接,生成hello.exe
运行结果如图所示:
可以看到,程序以正确的格式在屏幕正中间显示了字符串"welcome to masm!"
,完美地实现了功能;
项目完成