1. 需求
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 'welcome to masm!'
2. 分析
(1)材料中提到,一个在屏幕上显示的字符,具有前景(字符色)和背景(底色)两种颜色,字符还可以以高亮和闪烁的方式显示。前景色、背景色、闪烁、高亮等信息被记录在属性字节中,字节属性中,每位表示的含义如下
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
BL | R | G | B | I | R | G | B |
闪烁 | 背景(底色) | 高亮 | 前景(字符色) |
其中,R:红色,G:绿色,B:蓝色
可以按位设置属性字节,从而配出各种不同的前景色和背景色。
红底绿字,属性字节为:01000010b
红底闪烁绿字,属性字节为:11000010b
红底高亮绿字,属性字节为:01001010b
黑底白字,属性字节为:00000111b
白底蓝字,属性字节为:01110001b
所以,从以上材料的描述,我们可以得到
绿字的属性字节为:00000010b
绿底红色的属性字节为:00100100b
白底蓝色的属性字节为:01110001b
其次,材料中提到,在显示器中0行0列显示红底高亮闪烁绿色的字符串'ABCDEF'
(红底高亮闪烁绿色,属性字节为:11001010b,即CAh)
显示缓冲区的内容为:
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F | |
B800:0000 | 41 | CA | 42 | CA | 43 | CA | 44 | CA | 45 | CA | 46 | CA | . | . | . | . |
所以,一个字在显示缓冲区中,是用2个字节描述的,偶数字节是这个字的assii码,奇数字节是这个字的属性。
(2)材料中提到,B8000h ~ BFFFFh 共32kb空间,是80 x 25 彩色字符模式的显示缓冲区。显示缓冲区分为8页,每页 4kb(约等于 4000字节),显示器可以显示任意一页的内容。一般情况下,显示第0页的内容,也就是说,B8000h ~ B8F9Fh 这4000个字节的内容会显示在显示器上。
所以,从以上材料的描述,我们可以让显示缓冲区的段地址为:B8000h
其次,在一页显示缓冲区中,
偏移地址 000h ~ 09Fh 对应显示器上第1行(共160个字节,80个字(每个字用2个字节描述,底字节:assii码,高字节:字的属性))
偏移地址 0A0h ~ 13Fh 对应显示器上第2行
。。。
。。。
偏移地址 F00h ~ F9Fh 对应显示器上第25行(最后一行)
所以,在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串的字符串 'welcome to masm!',即:
- 在第12行的中间,偏移地址为:160*11 + 160/2 - 32/2 = 1824 处开始写入绿色字符串: 'welcome to masm!'
- 在第13行的中间,偏移地址为:160*12 + 160/2 - 32/2 = 1984 处开始写入绿底红色字符串: 'welcome to masm!'
- 在第14行的中间,偏移地址为:160*13 + 160/2 - 32/2 = 2144 处开始写入白底蓝色字符串: 'welcome to masm!'
3. 数据结构设计
我们可以用 C语言 数据结构的思想来组织需求中需要的数据
大概如C语言描述的如下结构
struct STR_8025 {
unsigned char str[16];
unsigned char attrs[3];
};
用汇编语言描述如下
data segment
db 'welcome to masm!' ;16个字节
db 00000010b ;1字节(绿色字)
db 00100100b ;1字节(绿底红色字)
db 01110001b ;1字节(白底蓝色字)
data ends
4. 代码
assume cs:code, ds:data, ss:stack
data segment
db 'welcome to masm!' ;16个字节, 看成C语言中的 uchar 类型字符
db 00000010b ;1字节(绿色字)
db 00100100b ;1字节(绿底红色字)
db 01110001b ;1字节(白底蓝色字)
data ends
stack segment
db 16 dup (0) ;16个db类型数据,并且初始化为0
stack ends
code segment
start:
;初始化数据段
mov ax, data
mov ds, ax
;初始化栈段
mov ax, stack
mov ss, ax
mov sp, 16 ;设置栈顶
mov ax, 0B800h ;B8000h ~ BFFFFh 共32kb空间,是80 x 25彩色字符模式的显示缓冲区
mov es, ax ;设置显示缓冲区的段地址在es寄存器上
mov si, 1824 ;在第12行的中间,偏移地址为:160*11 + 160/2 - 32/2 = 1824 处开始写入
mov cx, 3 ;需要写的行数
mov di, 0 ;字属性数据,10h[0], 10h[1], 10h[2]
rows:
push cx ;rows标号循环中的cx入栈
mov bx, 0
mov cx, 16 ;'welcome to masm!' 有16个字节
columns:
mov al, [bx] ;低字节存储字符对应的assii码编码值
mov ah, 10h[di] ;高字节存储字属性
mov es:[si], ax
inc bx ;移到下一个字
add si, 2 ;移到下一个字开始写的地址
loop columns
pop cx ;恢复rows标号循环中的cx
sub si, 32 ;每行写数据的首地址
add si, 160 ;移到下一行
inc di ;移到下一行属性
loop rows
mov ax, 4c00h
int 21h
code ends
end start