"Hello World"在Masm上的实现

项目情景

编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串”welcome to masm!”

分析

情景要求以及需要实现的功能非常简单,这里分析一下其中的几个要点:

  1. 字符串"welcome to masm!",查表可得其ASCII编码,不过也可以直接写到data段里,打印时再取用,将ASCII编码写入显示的字符所在字的低位字节即可;
  2. 中间,也即屏幕正中间,我们要打印的字符串长度为16,共打印3次,对于80x25(字符)的DOS屏幕,如果要显示在正中间,第1行应显示在第12行(偏移地址为780H)处,每行第1个字符应显示在该行的第32列处(偏移地址为40H),换行可以通过偏移地址+0A0H实现,因为每行显示80个字符,每个字符占2字节;
  3. 绿色绿底红色白底蓝色,可以通过调节属性字节实现更改,属性字节的格式如下:
    1
    2
    3
    7  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
4
data segment
db "w e l c o m e t o m a s m ! "
; 需要被打印的字符串
data ends

每个字符后面都加了一个空格,是为了以字的形式写入字符串,确保与显存中的位置拥有相同的偏移地址;

定义代码段code和程序起始点start:

1
2
3
4
5
code segment
start:
......
code ends
end start

由于没有需要暂存的数据(比如循环变量),所以这次的程序中不需要栈段;

初始化各段寄存器,使ds指向dataes指向显存:

1
2
3
4
5
mov 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
2
mov 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!
可以看到,程序以正确的格式在屏幕正中间显示了字符串"welcome to masm!",完美地实现了功能;
项目完成

~~~~~~~~~~~~~~ 本文已结束 感谢您的阅读 ~~~~~~~~~~~~~~