思路
- 先在data段中定义3行数据,每行32个单元,每行的前16个单元存放ASCII,每行后16个单元存放属性
- 将data段中的内容,传递到目标缓冲区,传递的过程中,每次从data单行中前16个单元中摘出1个,后16个单元中摘出1个,构成1个组合(每个组合由1个ASCII单元和1个属性单元构成)
代码
;实验9
assume cs:code,ds:data,ss:stack
data segment
;要显示的第1行:黑底绿字
db 'welcome to masm!'
db 16 dup (00000010b)
;要显示的第2行:绿底红字
db 'welcome to masm!'
db 16 dup (00100100b)
;要显示的第3行:白底蓝色
db 'welcome to masm!'
db 16 dup (01110001b)
data ends
stack segment;存放CX计数,使内、外两层循环均可使用CX
db 16 dup (0);最小的段区间就是16
stack ends
code segment
start:
;任何时候都是先实际关联
mov ax,data
mov ds,ax
mov ax,0B800h
mov es,ax;段寄存器必须借助中转
mov ax,stack
mov ss,ax
mov sp,16;栈底是第15,因为栈是0~15。则超尾是第16
;内循环用于对32个单元进行传送
;外循环用于换行,共有3行需要进行同样的内循环操作
mov bx,0;bx用于对显示缓冲区换行
mov bp,0;bp用于对源区换行
mov cx,3
s:
;只要进入循环,则cx已完成减1
;用完cx,在进入内循环前,马上存储cx值进栈。push的动作要放在s:之内,因为只要进入s,则cx完成减1,
;我们需要存储的是减少1之后的cx的值,如果push放在s之外,则cx仍然为3,会陷入无限循环
push cx
mov cx,16
mov si,0;源处ASCII区的首个单元
mov di,11*160+64;目标处ASCII区的首个单元
s0:
;以下ASCII和属性的传递,都无法采用ax的16位传递,因为需要从源处的2个区域内各提取1个,这2个数据所在单元没有相邻
;传递ASCII单元
mov al,ds:[si+bp]
mov es:[di+bx],al
;传递属性单元
mov al,ds:[si+16+bp]
mov es:[di+1+bx],al
inc si
add di,2
loop s0
add bp,32
add bx,160
;
;内循环的次数全部执行完毕后,cx将减为0,此时退出内循环,开始下一轮外循环。也就是说,push,pop仅在外循环使用即可
pop cx;
loop s
mov ax,4c00h
int 21h
code ends
end start