1:
输入线段的两个端点Point1和Point2,并且存储到Point1(x1,y1)和Point2(x2,y2)中;
2:
将Point1载入桢缓存,绘画第一个起始点;
3:
计算常量△x、△y、2△y和2(△y-△x),并且获得一个决策参数的第一个值:
P=2△y—△x;
4:
从n=0开始,在沿线经过每个Xn处,进行下面的检测:
如果Pn〈0,下一个点绘制的是(Xn+1,yn),并且Pn+1=Pn+2△y
如果P0〉=0,下一个点绘制的是(Xn+1,Yn+1),并且Pn+1=Pn+2(△y-△x)
5:
重复执行△x-1次步骤4;
B:
斜率k=1或斜率k=0时候的算法
对于斜率等于0或者斜率等于1时候,不需要通过算法直接的对于其中单一坐标变量进行处理。
C:
斜率k〈0的情况算法
将起始点和中止点坐标Point1和Point2交换,可以转化到斜率为0和1之内的算法去实现.
3.3圆形子程序设计
图5:
圆形子程序框架图
在圆绘制模块中同样是采用Bresenham画线算法。
先由键盘输入圆半径,再设置成图形模式.在调用圆Bresenham子程序将相关点堆栈,然后再调用圆画点子程序在屏幕上下左右四个点上向两边同时开始画点。
每画一个点就调用一下延时子程序实现绘图的动态显示。
3.4公共使用子程序设计
为了使程序结构较清晰,将三个子模块和主函数共同使用的子函数统一编写。
它们是数据输入子函数READ可以讲键盘输入的数据转化为16进制存在AX中。
在各个子函数的数据输入模块都是调用的这个子函数。
还有写像素子函数PIXEL。
它的作用是把经过Bresenham算法堆栈的数据用写像素的方法写在屏幕上。
延时子函数DELAY它的作用是延时使图像动态显示。
清屏CLEAR它的作用是调背景色清屏.便于在图形模式和文字模式之间进行转换。
在其中的延时子程序采用了双层循环的方法,因为各个子程序运行用时不同为了便于调试和取得更好的效果。
不同的子模块对应不同的延时子程序.
4.硬件原理
显示器有字符显示模式和图形显示两种工作方式
在图形方式下的屏幕由一个一个的像素做成。
通过读写屏幕上的各个像素就
可以显示出各种各样的图形。
在汇编语言中提供了多种图形显示模式。
设置模式的方法是:
AL=模式号,AH=00H,然后通过BIOS功能调用INT10H来实现.
表1常见的图形显示模式
显示模式号
分辨率
色彩数
适用显卡
0DH
320*200
16
EGAVGA
OEH
640*200
16
EGAVGA
0FH
640*350
2
EGAVGA
10H
640*350
16
EGAVGA
11H
640*480
2
MCGAVGA
12H
640*480
16
VGA
13H
320*200
256
MCGAVGA
VGA显卡上256KB显存,被划分为4个64KB的位平面。
比如屏幕上像素的位置是(X,Y),则改像素在显存位平面中字节地址的计算公式为:
字节地址=A0000H+Y*(640/8)+XMOD8(屏幕中有640列,每字节8位)
5.
调试结果
图6:
主菜单截屏
矩形绘制输入长168,宽100
图7:
矩形截屏
三角形输入
图8:
三角形截屏
图9:
圆形截屏
结束语
这次的微机课设用的时间很久,从接到题目分析。
到后来的程序编写调试费了很多的功夫。
收获很多,一方面是专业知识。
计算机怎么来显示图形,显存是怎么工作的。
怎样将内容直接写到内存中在屏幕上反映出来。
对这些知识有了更深入的了解,同时对于分支选择程序。
子程序的调用压栈出栈断点保护有了更深入的理解。
在程序就要调试完成的时候突然发现了一个致命的错误。
画完圆之后无法再画矩形.为了排查这个问题花了好长的时间一直没有解决。
后来经过请教同学和仔细的思考后发现。
在画圆程序中使用过CX,而在画矩形时矩形的大小是由CX来决定的。
虽然前面加入了压栈出栈,但是CX值已经被改变了。
再写入数据后只是把低位覆盖高位仍然是有数据的。
就造成了程序的错误.类似这样的错误还有很多.调试程序的过程也是一个不断检测错误不断反思的过程。
而且通过这次课设更是深入的体会到汇编语言做为底层语言在速度和大小方面有着很强的优势。
程序很小但是运行速度很快,功能能够实现的也很多.更重要的是可以直接的控制计算机的硬件.
在另一方面的收获就是兴趣也许在一开始时是很重要的,之后让人坚持下去的就是克服困难的勇气和决心.为了让程序的功能更加的多样化,我尝试着在其中添加各种各样的子程序。
大部分的想法都实现了,可以画出任意的三角,矩形和圆。
但是原本设想的图形移动和加入声音因为时间的原因没有再做。
算是一点遗憾吧.
在这次课设中自己也犯了一个错误,写比较大的程序时最好是和别人分工合作.相互讨论这样做的会更加完美一些,特别是在程序调试时有人商量一下是很好的可以发现一些自己不容易发现的问题和错误。
在这方面因为其他人想做别的题目所以没有这么做。
总的来说收获很多,想起了以前上的一门选修课。
夏老师讲的先整体再部分来设计系统。
还有对问题的思考方法在这次课设中让我少走了很多弯路.
参考文献
1.新编汇编语言程序设计,杨文显
2.微机原理与接口技术,周佩玲
3.80X86汇编语言程序设计,王元珍
4.汇编程序三角形画法,李永飞
附录1
主序代码部分
INCLUDEYLIB.H
DATASSEGMENT
;***********************************************
;主函数菜单使用的提示字符串
;***********************************************
MESS1DB0DH,0AH,"Welcomtomyprogram,I'mGaolingxiao.NO。
:
0120911350101$"
MESS2DB0DH,0AH,"Pleaseinputanumber(1—-3)tochoseaprogram:
$"
MESS3DB0DH,0AH,”Press1todrawasquareness$”
MESS4DB0DH,0AH,"Press2todrawatriangle$”
MESS5DB0DH,0AH,”Press3todrawacircle$"
MESS6DB0DH,0AH,"Yourchoice:
$”
MESS7DB0DH,0AH,"Press0tomainmeue,pressqtoquit:
$”
MESS8DB0DH,0AH,”sorry!
Inputerroe。
$"
MESS9DB0DH,0AH,"Pressqtoquit$”
;***********************************************
;各个子函数公共使用的数据定义部分
;***********************************************
COLORDW02
BKCOLORDW0;黑色为0
BUFFERDB6,?
,6DUP(?
);输入函数暂存buffer
C10DW10
;***********************************************
;圆用的数据段定义和提示语
;***********************************************
MESS1_CDB0DH,0AH,"Pleaseinputtheradius(1--200):
$”
OL_CDB?
;保存原来屏幕格式用
XDW280;圆心位置
YDW240
RADIUSDW150;半径长度
;***********************************************
;矩形用的数据段定义和提示字符串
;***********************************************
OL_SDB?
;矩形的原来图像模式
X_SDW50;矩形的起始坐标
Y_SDW50;矩形的起始坐标
L_SDW?
W_SDW?
COLOR_SDB2
MESS1_SDB0DH,0AH,"Pleaseinputthelength(1--500):
$"
MESS2_SDB0DH,0AH,”Pleaseinputthewidth(1—-500):
$"
MESS3_SDB0DH,0AH,”Press0tomainmenu,1todrawagain,otherkeytoquit.$”
;***********************************************
;三角用的数据段定义和提示字符
;***********************************************
POINTDB24,?
24DUP(?
)
OL_TDB?
MESS1_TDB0DH,0AH,”Pleaseinputthefristpoint$"
MESS2_TDB0DH,0AH,”Pleaseinputthesecondpoint$"
MESS3_TDB0DH,0AH,”Pleaseinputthethirdpoint$”
MESS5_TDB0DH,0AH,”X:
$"
MESS6_TDB0DH,0AH,"Y:
$"
MESS7_TDB0DH,0AH,”Inputerror$"
DATASENDS
STACKSSEGMENT
DW100DUP(0)
STACKSENDS
CODESSEGMENT
ASSUMECS:
CODES,DS:
DATAS
START:
MOVAX,DATAS
MOVDS,AX
LEADX,MESS1
MOVAH,9
INT21H
;***********************************************
;显示主菜单提示字符串
;***********************************************
DISPLAY:
LEADX,MESS2
MOVAH,9
INT21H
LEADX,MESS3
MOVAH,9
INT21H
LEADX,MESS4
MOVAH,9
INT21H
LEADX,MESS5
MOVAH,9
INT21H
LEADX,MESS9
MOVAH,9
INT21H
LEADX,MESS6
MOVAH,9
INT21H
;***********************************************
;主菜单选择部分
;***********************************************
INPUT:
MOVAH,1
INT21H
CMPAL,'1’
JBDISPLAY
JESQUAR
CMPAL,’2’
JETRIA
CMPAL,’3'
JECRIC
CMPAL,’q’
JEOUTPUT
JMPDISPLAY
SQUAR:
;矩形子程序的入口部分
CALLSQUAR_P
JMPOUTPUT
TRIA:
;三角子程序的入口部分
CALLTRIA_P
JMPOUTPUT
CRIC:
;圆形子程序的入口部分
CALLCRIC_P
JMPOUTPUT
OUTPUT:
;退出程序段
MOVAH,9
INT21H
MOVAH,4CH
INT21H
;***********************************************
;方块绘制子程序段
;***********************************************
SQUAR_PPROCNEAR
PUSHCX
LONG:
;输入矩形的长度部分
LEADX,MESS1_S
MOVAH,9
INT21H
XORAX,AX
CALLREAD;调用输入子函数数据放在AX
CMPAX,0
JBLONG_ER
CMPAX,01F4H
JALONG_ER
MOVWORDPTR[L_S],AX
JMPWIDTH_S
LONG_ER:
;在输入错误时的程序段
CALLINPUT_ER
JMPLONG
WIDTH_S:
;输入矩形的宽度部分
LEADX,MESS2_S
MOVAH,9
INT21H
XORAX,AX
CALLREAD;调用输入子函数数据放在AX
CMPAX,0
JBWIDTH_ER
CMPAX,01F4H
JAWIDTH_ER
MOVWORDPTR[W_S],AX
MOVAH,0FH
INT10H
MOVOL_S,AL
SETMODE12H;设置640*480*16图形模式
XORCX,CX;将CX清零,防止干扰
MOVCX,WORDPTR[L_S]
MOVDX,Y_S
JMPL1_S
WIDTH_ER:
;在输入错误时的程序段
CALLINPUT_ER
JMPWIDTH_S
L1_S:
;画第一条直线
PUSHCX;压栈保护
WRITE_PIXEL0,Y_S,X_S,COLOR_S;调用写像素的宏命令
CALLDELAY_S;延时实现动态效果
INCX_S
POPCX
LOOPL1_S;循环画点
XORCX,CX
MOVCX,WORDPTR[W_S];将宽度存入CX
L2_S:
PUSHCX;画第二条直线
WRITE_PIXEL0,Y_S,X_S,COLOR_S
CALLDELAY_S
INCY_S
POPCX
LOOPL2_S
XORCX,CX
MOVCX,WORDPTR[L_S]
L3_S:
;画第三条直线
PUSHCX
WRITE_PIXEL0,Y_S,X_S,COLOR_S
CALLDELAY_S
DECX_S
POPCX
LOOPL3_S
XORCX,CX
MOVCX,WORDPTR[W_S]
L4_S:
;画第四条直线
PUSHCX
WRITE_PIXEL0,Y_S,X_S,COLOR_S
CALLDELAY_S
DECY_S
POPCX
LOOPL4_S
MOVAH,0
INT16H
MOVAH,0
MOVAL,OL_S;恢复原来屏幕格式
INT10H
LEADX,MESS3_S;提示菜单信息
MOVAH,9
INT21H
MOVAH,1
INT21H
CMPAL,'1'
JELONG
CMPAL,'0'
JEDISPLAY
CMPAL,’q’
JEOUTPUT
POPCX
JEOUTPUT
RET
SQUAR_PENDP
;***********************************************
;三角绘制子程序
;***********************************************
TRIA_PPROCNEAR
PUSHCX
CALLINPUT_T
MOVAH,0FH
INT10H
MOVOL_T,AL;保存原来屏幕格式,用来恢复的
MOVAX,0A000H;显存
MOVES,AX
SETMODE12H;设置640*480*16图形模式?
?
?
?
LEASI,POINT
NEXT:
MOVAX,0012H
INT10H
MOVAL,2
CALLSET_WRITE_MODE
MOVAX,BKCOLOR
CALLCLEAR;将背景清成黑色
CALLOUTPUT_T;调用输出子函数
MOVAH,0
INT16H
MOVAH,0
MOVAL,OL_T
INT10H
LEADX,MESS3_S;提示菜单
MOVAH,9
INT21H
MOVAH,1
INT21H
CMPAL,'0'
JEDISPLAY
CMPAL,'q'
POPCX
JEOUTPUT
RET
TRIA_PENDP
;***********************************************
;圆绘制子程序
;***********************************************
CRIC_PPROCNEAR
MOVAX,DATAS
MOVDS,AX
INPUT_C:
;半径输入程序段
LE