; 实验9
; 编程: 在屏幕中间分别显示绿色,绿底红色,白底蓝色的字符串'welcome to masm!'
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 背景知识:80×25彩色字符模式显示缓冲区的结构
;
; 内存地址空间中,B8000H~BFFFFH共32KB的空间,为80×25彩色字符模式的显示缓冲区。
; 向这个地址空间写入数据,写入的内容将立即出现在显示器上。
;
; 在80×25彩色字符模式下,显示器可以显示25行,每行80个字符,每个字符可以有256种
; 属性(背景色、前景色、闪烁、高亮等组合信息)。
;
; 这样一个字符在显示缓冲区中就要占两个字节,分别存放字符的ASCII码和属性,80×25
; 模式下,一屏的内容在显示缓冲区中共占4KB。
;
; 显示缓冲区分为8页,每页4KB,显示器可以显示任意一页的内容。一般情况下,显示第0
; 页的内容。也就是说通常情况下,B8000H~B8F9FH中的4KB的内容将出现在显示器上。
;
; 在一页显示缓冲区中:
; 偏移000~09F对应显示器上的第1行(80个字符占160个字节);
; 偏移0A0~13F对应显示器上的第2行;
; 偏移140~1DF对应显示器上的第3行;
; ... ...
; 偏移F00~F9F对应显示器上的第25行。
;
; 在一行中,一个字符占两个字节的存储空间(一个字),低位字节存储字符的ASCII码,
; 高位字节存储字符的属性。一行共有80个字符,占160个字节。
; 即在一行中:
; 00~01单元对应显示器上的第1列;
; 02~03单元对应显示器上的第2列;
; 04~05单元对应显示器上的第3列;
; ... ...
; 9E~9F单元对应显示器上的第80列。
;
; 在显示缓冲区中,偶地址存放字符,奇地址存放字符的颜色属性。
; 属性字节的格式:
; 7 6 5 4 3 2 1 0
; 含义 BL [R G B] I [R G B]
; 闪烁 背景 高亮 前景
; R:红色
; G:绿色
; B:蓝色
; 注:闪烁的效果必须在全屏DOS方式下才能看到。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 分析:
; 1) 按位设置属性字节
; 绿色: 00000010B
; 绿底红色: 00100100B
; 白底蓝色: 01110001B
;
; 2) 程序要求在屏幕中间分别显示;
; *为外部窗口边框,不占用显示缓冲区字节
;
; 01234... ... 32 47 ... 79
; **********************************************************************************
; 0 * *
; 1 * *
; 2 * *
; 3 * *
; 4 * *
; 5 * *
; 6 * *
; 7 * *
; 8 * *
; 9 * *
; 10* *
; 11* welcome to masm! *
; 12* welcome to masm! *
; 13* welcome to masm! *
; 14* *
; 15* *
; 16* *
; 17* *
; 18* *
; 19* *
; 20* *
; 21* *
; 22* *
; 23* *
; 24* *
; **********************************************************************************
;
; 'welcome to masm!'共有16个字符,需占用显示缓冲区32个字节。
; 可写到显示缓冲区第0~7页中的任意一页,我们写到第0页。
; 第0页地址从B8000H~B8F9FH,共占4KB,而我们需要把三行写到这一页的中间三行,
; 中间三行的第一行在该页中的地址为:
; 160*((25-3)/2*)+(160-32)/2=1824=0720H
; 对应的实际缓冲区地址为:
; B8000H + 0720H = B8720H
; 或者用段地址表示为 B872H:0000H
assume cs:code,ds:data
data segment
db 'welcome to masm!'
db 0000001B,00100100B,01110001B ;字符属性值
data ends
code segment
start: mov ax,data
mov ds,ax
mov ax,0b872H ;三个字符串中第一个的首地址
mov es,ax
mov bx,16 ;字符属性值首地址
mov cx,3 ;三行字符串
s: mov dx,cx
mov si,0
mov di,0
mov ah,[bx] ;ah=字符属性值
inc bx
mov cx,16
s0: mov al,[si] ;al=字符ASCII码
mov es:[di],ax
inc si
add di,2
loop s0
mov ax,es ;指向下一个字符串
add ax,0ah ;每行160个字节,相当于段地址增加10
mov es,ax
mov cx,dx
loop s
mov ax,4c00h
int 21h
code ends
end start |