汇编语言实现图形绘制
一、准备工作
1.INT 10H的功能
INT 10H 是由 BIOS 对屏幕及显示器所提供的服务程序。使用 INT 10H 中断服务程序时,先指定 AH 寄存器编,该编号表示欲调用的功用,然后再定义其它寄存器内容,当一切设定好之后再调用 INT 10H。下面是我们在程序中用到的指令:
AH=00H
AH=00/INT 10H 是用来设定显示模式的服务程序,AL 寄存器表示欲设定的模式
;AL部分模式说明
mov al,12h ;640*480 256的图形模式:
mov al,13h ;320*200 256色的图形模式:
;完整调用
mov al,13h ;320*200 256色的图形模式:
mov ah,0 ;是用来设定显示模式的服务程序
int 10h
AH=0CH
AH=0Ch/INT 10H 是在绘图模式中显示一点 ( 也就是写入点像),而 AH=0DH/INT 10H 则是读取点像。
写入时,要写入位置 X 坐标存于 CX 寄存器,Y 坐标存于 DX 寄存器,颜色存于 AL 寄存器。对于汇编的显示窗口,左上角为原点,向右为X轴,越往右X数值越大;向下为Y轴,越往下Y数值越大。X、Y坐标的边界以及颜色的种类则和之前定义的显示模式相关。
显示模式 | X 座标 | Y 座标 | 颜色 |
4 | 0~319 | 0~199 | 0、1 |
5 | 0~319 | 0~199 | 0~3 |
6 | 0~639 | 0~199 | 0、1 |
AH=0DH/INT 10H 则是读取某一位置之点像,您必须指定 CX、DX,而 INT 10H 会传回该位置点像之颜色。
;完整调用
mov cx,10 ;x坐标
mov dx,10 ;y坐标
mov al,1100b ;淡红色
mov ah,0ch ;写入点像
int 10h ;调用中断
二进制数 | 颜色 | 例子 | 二进制数 | 颜色 | 例子 |
0000 | 黑色 | black | 1000 | 灰色 | gray |
0001 | 蓝色 | blue | 1001 | 淡蓝色 | light blue |
0010 | 绿色 | green | 1010 | 淡绿色 | light green |
0011 | 青色 | cyan | 1000 | 淡青色 | light cyan |
0100 | 红色 | red | 1100 | 淡红色 | light red |
0101 | 紫红色 | magenta | 1101 | 淡紫红色 | light magenta |
0110 | 棕色 | brown | 1110 | 黄色 | yellow |
0111 | 银色 | light gray | 1111 | 白色 | white |
2.Bresenham直线算法
对于直线、竖线的绘制,方法比较简单
而对于斜线的绘制,则存在一些问题。因为我们的屏幕是由像素点构成,而像素点的坐标都是整数,但是在直线上每一点的坐标不一定是整数,所以我们将要对该点进行近似处理,选取屏幕上最接近该点的像素点进行绘制。
Bresenham直线算法就是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。是计算机图形学中最先发展出来的算法。
我们以0<K<1的斜线为例:
若图,该算法的核心思想:
当前点为A(X,Y),由于K的限制性,下一个绘制的点为B(X+1,Y)或者C(X+1,Y+1)。而直线上的点为C点,该点介于B点和D点之间,所以我么就要判断C点是偏向于B点还是D点。其中一种方法是将(X+1,Y+1/2)带入直线方程F中:
若F(X+1,Y+1/2)> 0,则证明B、D之间的中点在直线上方,则选取B点为下一个绘制的像素点。
若F(X+1,Y+1/2)< 0,则证明B、D之间的中点在直线下方,则选取D点为下一个绘制的像素点。
在知道核心思想之后,为了提高运行效率,该算法通过一系列复杂的数学公式简化了运算方式(有兴趣的同学可以去了解一下),只会用到较为快速的整数加法、减法和位元移位就能完成上述操作,最终运算结果如下:
对于直线y=kx+b(已知两点(x1,y1)(x2,y2),设y2>y1,△y=y2-y1,△x=|x2-x1|)
推导过程:
P=△y-1/2 = f(x+1)-f(x)-1/2= kx+k-kx-1/2=k-1/2=△y/△x - 1/2 为了简化运算,两边同乘2△x,由于我们只需要看左边符号,所以忽略△x,最终结果如下:
P=2△y-△x
1、0<K<1(X+1,判断Y)
Pn=2△y-△x
若Pn < 0,下一个绘制点为(X+1,Y),Pn+1=Pn+2△y
若Pn >= 0,下一个绘制点为(X+1,Y+1),Pn+1=Pn+2(△y-△x)
2、K>1(Y+1,判断X)
Pn=2△y-△x
若Pn < 0,下一个绘制点为(X,Y+1),Pn+1=Pn+2△x
若Pn >= 0,下一个绘制点为(X+1,Y+1),Pn+1=Pn+2(△x-△y)
3、-1<K<0(X-1,判断Y)
Pn=2△y-△x
若Pn < 0,下一个绘制点为(X-1,Y),Pn+1=Pn+2△y
若Pn >= 0,下一个绘制点为(X-1,Y+1),Pn+1=Pn+2(△y-△x)
4、K<-1(Y+1(y2>y1),判断X)
Pn=2△y-△x
若Pn < 0,下一个绘制点为(X,Y+1),Pn+1=Pn+2△x
若Pn >= 0,下一个绘制点为(X-1,Y+1),Pn+1=Pn+2(△x-△y)
二、代码实现
1、直线
;横线
;mov al,12h ;640*480 256的图形模式:
mov al,13h ;320*200 256色的图形模式:
mov ah,0 ;是用来设定显示模式的服务程序
mov cx,10 ;x坐标
mov bx,100 ;终止x坐标
mov dx,10 ;y坐标
int 10h
pheng:
mov al,1100b ;淡红色
mov ah,0ch ;写入点像
inc cx
cmp cx,bx
int 10h
jne pheng
运行结果:
2、竖线
;竖线
;mov al,13h ;320*200 256色的图形模式:
;mov ah,0 ;是用来设定显示模式的服务程序
mov cx,10 ;x坐标
mov bx,100 ;终止x坐标
mov dx,10 ;y坐标
;int 10h
pshu:
mov al,1100b ;淡红色
mov ah,0ch ;写入点像
inc dx
cmp dx,bx
int 10h
jne pshu
运行结果:
3、斜线
mov al,13h ;320*200 256色的图形模式:
mov ah,0 ;是用来设定显示模式的服务程序
int 10h
mov x1,20
mov x2,70
mov y1,10
mov y2,200
mov ax,x2
mov bx,x1
cmp ax,bx
jae dpos1
sub bx,ax
mov s1,-1
mov xd,bx
jmp d1
dpos1:
sub ax,bx
mov s1,1
mov xd,ax
d1:
mov ax,y2
mov bx,y1
cmp ax,bx
jae dpos2 ;y2>=y1
sub bx,ax ;y2<y1
mov s2,-1
mov yd,bx
jmp d2
dpos2:
sub ax,bx
mov s2,1
mov yd,ax
d2:
add ax,ax
mov bx,xd
sub ax,bx
mov p,ax ;2dy-dx
mov cx,x1
mov dx,y1
pxie:
mov al,1100b ;淡红色
mov ah,0ch ;写入点像
int 10h
mov ax,p
mov bx,0
cmp ax,bx
jge ppos ;p>=0
jl pneg ;p<0
ppos:
mov ax,xd
mov bx,yd
cmp ax,bx
ja ddpos1 ;xd>yd
jbe ddneg1 ;xd<=yd
ddpos1: ;0<k<1 或者 -1<k<0 同时 p>=0
mov ax,x1 ;x=x+1
mov bx,s1
add ax,s1
mov x1,ax
mov ax,s2 ;y=y+1
mov bx,y1
add bx,ax
mov y1,bx
mov ax,p ;Pn+1=Pn+2(dy-dx)
mov bx,xd
mov cx,yd
add bx,bx
add cx,cx
sub cx,bx
add ax,cx
mov p,ax
jmp plot
ddneg1: ;k>1 或者 k<-1 同时 p>=0
mov ax,y1 ;y=y+1
inc ax
mov y1,ax
mov ax,s1 ;x=x+1 或者 x=x-1
mov bx,x1
add bx,ax
mov x1,bx
mov ax,p ;Pn+1=Pn+2(dx-dy)
mov bx,xd
mov cx,yd
add bx,bx
add cx,cx
sub bx,cx
add ax,bx
mov p,ax
jmp plot
pneg:
mov ax,xd
mov bx,yd
cmp ax,bx
ja ddpos2 ;xd>yd
jbe ddneg2 ;xd<=yd
ddpos2: ;0<k<1 或者 -1<k<0 同时 p<0
mov ax,x1 ;x=x+1
mov bx,s1
add ax,s1
mov x1,ax
mov ax,p ;Pn+1=Pn+2dy
mov bx,yd
add bx,bx
add ax,bx
mov p,ax
jmp plot
ddneg2: ;k>1 或者 k<-1 同时 p<0
mov ax,y1 ;y=y+1
inc ax
mov y1,ax
mov ax,p ;Pn+1=Pn+2dx
mov bx,xd
add bx,bx
add ax,bx
mov p,ax
jmp plot
plot:
mov cx,x1 ;X坐标
mov dx,y1 ;Y坐标
cmp cx,x2 ;是否绘图完毕
jne pxie
运行结果:
由于分辨率较低,所以斜线比较粗糙
根据上述程序即可完成三角形、矩形等图形的绘制:
将上述程序封装为子程序,三角形即可调用两次斜线子程序,一次横线子程序完成绘制;矩形可调用两次横线、两次竖线子程序完成绘制。
在绘制等边三角形时,由于等边三角形具有其特殊性,所以在代码方面可存在一定优化,如果感兴趣可看下篇文章。