; 王爽-汇编语言-第9章
; 完成目标:在屏幕中间分别显示绿色,绿底红色,白底蓝色的字符串“welcome to masm!”
; 其它需要知道的知识点:
; 1. 内存空间中,B8000H-BFFFFH共32KB的空间,为80X25彩色字符模式的显示缓冲区,向这个地址空间写入数据,写入地数据将立架出现在显示器山。
; 1. 显示器显示25行,每行80个字符,每个字符可以有256种属性。
; 2. 一个字符在显示缓冲区就要占两个字节,分别存放字符的ASCII码和属性。
; 3. 一屏的内容在显示缓冲区中共占4000个字节。 80x25=2000
; 4. 一个字节,低位字节存储字符的ASCII码,高位字节存储字符的属性。
; 5. 7 6 5 4 3 2 1 0
; BL R G B I R G B
; 闪烁 背景色 高亮 前景
;
; 6. 如: 黑底绿字: 0000 0010B => 02H
; 闪烁+绿底白字: 1010 0100B => A4H
; 白底蓝字: 0111 0001B => 71H
;
; 7. ‘welcome to masm!’对应的十六进制为:77H, 65H, 6CH, 63H, 6FH, 6DH, 65H, 20H, 74H, 6F, 20H, 6DH, 61H, 73H, 6D, 21H。
; 7. 闪烁的效果必须在全屏DOS下才能看到。(后在DOSBox下实验,不用全屏也能看到效果)
;
; 准备开始完成,进行如下分析:
;
; 1. 本书总的寄存器:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW。
;
; 2. 总结寄存器的作用, 准备灵活分配使用寄存器:
;
; ds:数据段; cs:代码段; ss:栈段;
; ip:代码段偏移; sp:栈段偏移
; bx, si, di, bp 寻址变量
; cx: 循环变量
;
; 3. 其它可用的空闲寄存器:
; ax:常给ds赋值; dx:
; es:可用于段前缀
; psw:暂不知道做什么用
;
; 4. 总共35行,那么在中间位置我们用第12,13,14行来显示目标字符串。
; 5. 目标字符串总共16个字符:字母,空格和标点符号。每列显示80个字符,中间显示,我们从每行第32个字符开始显示内容,即第64个字节处开始显示。
; 6. 计算显示字符的位置为:
; 12*160+64 => 1984 => 07C0H
; 13*160+64 => 2144 => 0860H
; 14*160+64 => 2304 => 0900H
; 7. 寄存器分析:
; cx作为行显示3行的行循环和移动字符列循环。es:写入的段寄存器。bx:颜色在数据段的索引。di:每行开始位置在数据段的索引。si:字符在数据段的索引。bp:每个字符具体的显示位置。al:存储字符的ASCII码。ah:存储字符的属性。
assume cs:codesg, ds:datasg, ss:stacksg
datasg segment
db 'welcome to masm!' ; 显示的字符
db 02H, 0A4H, 71H, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 显示字符的颜色
dw 12*160+64, 13*160+64, 14*160+64, 0, 0, 0, 0, 0 ; 显示字符开始位置
datasg ends
stacksg segment ; 定义一个栈段,容量为16个字节
dw 0,0,0,0,0,0,0,0
stacksg ends
codesg segment
start:
mov ax, stacksg ; 设置栈段
mov ss, ax
mov sp, 16
mov ax, datasg ; 设置数据段
mov ds, ax
mov ax, 0B800H ; 设置目标段地址,存储写入显示器的数据
mov es, ax
mov cx, 3 ; 行索引3
mov bx, 16 ; 颜色从数据段的16个字节开始
mov di, 32 ; 显示位置从数据段的32个字节开始
s0: push cx ; 将外层循环压栈
mov cx, 16 ; 10H
mov bp, [di] ; 初始化显示位置
mov si, 0
s1:
mov al, [si] ; 低位字节写存储字符的ASCII码
mov ah, [bx] ; 高位字节写存储字符的属性
mov es:[bp], ax
inc bp
inc bp ; 1个字符占用的是2个字节,需要+2
inc si ; 下一个显示的字符
loop s1
pop cx
add bx, 1 ; 使用下一个颜色
add di, 2 ; 下一个显示字符开始位置
loop s0
mov ax,4c00H
int 21H
codesg ends
end start
; 后经测试:
; 1. 若要在左上角显示:那么此值为:1*160+0,意思是从第1行开始计算,不是从第0行开始计算。
; 2. si 作为显示缓冲区偏移地址,如果此值设置为0,将不会有任何显示。