设计一个在屏幕上显示的动画
1、用DOS, BIOS功能编写静止画面的子程序,也可以选择用直接写显存的方法实现
2、编写擦除、移动画面的子程序
3、编写延时子程序
4、编写实现动画程序
[此贴子已经被作者于2007-7-2 20:36:50编辑过]
参考资料:
在屏幕上显示一个从左向右行走的彩色机器人。
(1)分析
就是在屏幕上写字母,在屏幕不同位置写7个字母后,就形成一个机器人。当画完一个机器人,延迟一段时间后清除机器人,修改行号重新画机器人,如此循环一直到画完一行。清除机器人过程类似画机器人,只是写字符颜色与背景色相同,流程图如下。
(2)程序
;功能调用宏定义
;寄存器压入堆栈宏定义
Pushr macro x,y,z,w
Push x
Push y
Push z
Push w
Endm
;堆栈顶数据弹出到寄存器宏定义
Popr macro x,y,z,w
Pop w
Pop z
Pop y
Pop x
Endm
;定义堆栈段
Stacks segment
Dw 256 dup(?)
Stacks ends
;定义数据段
Data segment ;修改下面蓝色的字改变图形
Robot db 7 ;机器人由7和符号组成
Db 5ch,8eh,0,0 ;左手,字符属性,行偏移,列偏移
Db 08h,06h,0,1 ;胸部,字符属性,行偏移,列偏移
Db 2fh,8eh,0,1 ;右手,字符属性,行偏移,列偏移
Db 0dbh,0ah,1,-1 ;腹部,字符属性,行偏移,列偏移
Db 13h,7h,1,0 ;两腿,字符属性,行偏移,列偏移
Db 02h,84h,-3,0 ;面部,字符属性,行偏移,列偏移
Db 9dh,94h,-1,0 ;天线,字符属性,行偏移,列偏移
Count dw 0 ;保存字符个数
Pointer dw 0 ;保存字符首地址
Line db 0 ;保存行号
Column db 0 ;保存列号
Data ends
Codes segment
Assume cs:codes,ds:data,es:data,ss:stacks
Start: mov ax,data
Mov ds,ax
Mov es,ax
;设置为80×25彩色文本方式
mov ah,0
mov al,3
int 10h
;清屏幕
Call clear
Lea di,robot ;数据段首地址送DI
Mov dx,0808h ;显示的起始行号和列号
Mov bh,0
Call moves ;调用MOVES子程序
Call clear ;清屏幕
Mov ah,4ch ;主程序结束返回DOS
Int 21h
Moves proc ;机器人移动子程序
Pushr ax,bx,cx,dx ;保存寄存器内容
Push di
Xor ch,ch
Mov cl,[di] ;字符个数送CX
Inc di ;指向第一个显示符号
Mov count,cx ;保存字符个数
Mov pointer,di ;保存字符首地址
Mov line,dh ;保存行号
Mov column,dl ;保存列号
Next: add dh,[di+2] ;根据偏移值计算下一个符号的行号
Add dl,[di+3] ;计算列号
Cmp dl,80 ;判断是否到屏幕最右端
Jb write ;否,继续画
Pop di
Popr ax,bx,cx,dx
Ret
Write: mov ah,2
Int 10h ;设置光标位置
Mov al,[di] ;取字符
Mov bl,[di+1] ;取字符属性
Push cx ;保存计数值
;设置写彩色字符
mov ah,9
mov cx,1
int 10h
Pop cx ;恢复计数值
Add di,4 ;指向下一个显示字符
Loop next ;机器人没画完转next
Call delay ;延时子程序
Call Erase ;清除机器人子程序
Jmp short next
Moves endp
Erase proc
Mov cx,count ;字符个数送CX
Mov di,pointer ;字符首地址送DI
Mov dh,line ;行号送DH
Mov dl,column ;列号送DL
l: add dh,[di+2] ;根据相对偏移计算行号
mov ah,2 ;设置光标位置
add dl,[di+3]
int 10h
mov al,[di] ;取字符
mov bl,0 ;字符属性为黑底黑字
push cx
mov ah,9 ;写字符
mov cx,1
int 10h
pop cx
add di,4 ;指向下一个字符
loop l ;未清除完转L
mov cx,count ;为重画机器人做准备
mov di,pointer
在这里加一句,dec或inc line,上下移动
mov dh,line
inc column ;inc向左走,dec向右走
mov dl,column
ret
erase endp
delay proc ;延时子程序
pushr ax,bx,cx,dx
mov dx,2000
go: mov cx,5000
repeat: loop repeat
dec dx
jne go
popr ax,bx,cx,dx
ret
delay endp
clear proc ;清屏幕子程序
pushr ax,bx,cx,dx
mov bh,7
mov dx,184fh
mov ax,0600h
mov cx,0
int 10h
popr ax,bx,cx,dx
ret
clear endp
codes ends
end start
附:
彩色文本方式的显示属性(BL的值)
位号 D7 D6 D5 D4 D3 D2 D1 D0
属性 闪烁 背景颜色 字符颜色
1 闪烁 000 黑 0000 黑
0 不闪烁 001 蓝 0001 蓝
010 绿 0010 绿
011 青 0011 青
100 红 0100 红
101 品红 0101 品红
110 棕 0110 棕
111 白 0111 灰白
1000 灰
1001 浅蓝
1010 浅绿
1011 浅青
1100 浅红
1101 浅品红
1110 黄
1111 白
二、直接改变显存内容显示:
1、显存空间分配:
内存地址空间中,B8000H-BFFFFH共32KB的空间,为80×25彩色字符模式显示缓冲区。向这个地址空间写入数据,写入的内容将立即出现在显示器上。
80×25=2000个字符,每个字符在缓冲区中占2个字节,一个字节存放ASC码,一个字节存放字符属性(字符颜色、字符背景颜色、闪烁、高亮度)
2、偏移地址计算:
如第2行,第40列 :(2-1)×160+40×2 这个偏移地址中存放字符的ASC码,
(2-1)×160+40×2+1这个偏移地址中存放字符的属性
第M行,第N列的一般计算公式为:
(M-1)×160+N*2 存放ASC码
(M-1)×160+N*2+1 存放属性
例:用直接写显存法,在屏幕第3行第40列显示'welcome to masm!'
assume cs:code
data segment
db 'welcome to masm!'
data ends
code segment
start:mov ax,data
mov ds,ax
mov ah,6 ;上滚当前页
mov al,0 ;行数,0为整个屏幕
mov ch,0 ;区域坐标
mov cl,0
mov dh,24
mov dl,79
mov bh,7 ;黑底白字
int 10h
mov bx,0
mov ax,0b800h
mov es,ax
mov si,0
mov cx,16
s: mov ah,[bx]
mov es:[si+400],ah ;160*2+40*2=400 即第3行第40列位置
inc si
inc bx
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start