实验9 根据材料编程 (材料详见书上188页)
编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 ’welcome to masm!’
材料:
80X25彩色字符模式显示缓冲区的结构:
内存地址空间中,B8000H~BFFFFH共32KB的空间,该模式下显示器可以显示25行,每行80个字符,每个字符可以有256种属性(背景色、前景色、闪烁、高亮等组合信息)。
这样,一个字符在显示缓冲区中共占两个字节,分别存放字符的ASCII码和属性。80X25模式下,一屏的内容在显示缓冲区中共占4000个字节。
显示缓冲区分为8页,每页4KB(约4000B),显示器可以显示任意一页的内容。一般情况下,显示第0页的内容。也就是说通常情况下,B8000H~B8F9FH中的4000个字节的内容将出再在显示器上。
在一行中,一个字符占两个字节的存储空间( 一个字),低位字节存储字符的ASCII码,高位字节存储字符的属性。一行共点有80个字符,点160个字节。
属性字节的格式:
二进制位 7 6 5 4 3 2 1 0
对应含义 BL R G B I R G B
闪烁 背 景 高亮 前 景
注意,闪烁的效果必须在全屏DOS方式下才能看到。
以下是我解答的完整的代码:
:>----------------------------------------------------------------------------------------
assume cs: codesg, ds:datasg, ss:stacksg
datasg segment
db 'welcome to masm!' ;要显示的数据内容共16个字节
datasg ends
stacksg segment
dw 0,0,0,0,0,0,0,0 ;这里用栈来保存数据
stacksg ends
codesg segment
color1: mov ah, 00000010B ;绿色的字
jmp ok
color2: mov ah, 00100100B ;绿底红字
jmp ok
color3: mov ah, 01110001B ;白底蓝字
jmp ok
;程序入口
start: mov ax, datasg
mov ds, ax
mov ax, 0B800H
mov es, ax ;显存空间段的首地址用es段寄存器保存
mov di, 0780H ;用di来在行之间移动,当前di的值为第12行的首地址
mov cx, 3H ;要显示3行数据内容,cx=3
s0: push cx ;下面有循环嵌套也要用到cx,把它入栈保存,并进入外层循环中
mov dx, cx ;dx与外层循环的cx值同步,并用来做比较运算进行不同颜色
; 的配置跳转(即 color1、color2、color3)
mov si, 0H ;si与ds结合使用,用来在datasg(ds段中)中取数据,按字节长度逐个取出
mov bx, 0H ;bx用来在显示缓存是进行列移动,
; 每次移动两个字节(因为一个字符要显示,要占两个字节)
mov cx, 10H ;共处理16个字符
s1: mov al, [si] ;将字符的ASCII码值(占一个字节长度)赋给al,并进入内层循环中
cmp dx, 0003H ;与3比较是否是第一个要显示的行,即显示绿色的的文字
jz color1
cmp dx, 0002H ;与2比较是否是第二个要显示的行,即显示绿底红字的文字
jz color2
cmp dx, 0001H ;与3比较是否是第三个要显示的行,即显示白底蓝字的文字
jz color3
ok: mov es:[bx][di].40H, ax ;将带有属性字节的显示字符添加到对应的缓存位置
inc si ;加1处理下一个要显示的字符
add bx, 2H ;加2跳到下一个缓存位置
loop s1
add di, 0A0H ;加160(A0H)跳到显存的下一行首地址
pop cx ;回到外层循环体,还原cx在外层循环中的值
loop s0
mov ax, 4c00H
int 21H
codesg ends
end start
:<----------------------------------------------------------------------------------------
总结:
终于可以操作显存控制显示内容了,激动呀!对循环的嵌套还不熟,起初还被我搞成了死循环晕~ ~ ~
------------- 以上的习题部分及代码引用于王爽老师的<<汇编语言>>第二版 ----------------