📄 tuxing.asm
字号:
直线、圆等图形函数的汇编语言实现
向远
本例所用的绘图函数均采用堆栈的方法传递参数,可以和C语言接口。画点的函数采用直接写显存的方法。为了直接由CPU数据确定像素颜色,而不使用位屏蔽寄存器或置位/重置寄存器,采用了VGA的写模式2方式。直线和圆的算法均采用Bresenham算法实现,其实现过程及堆栈状态均有较详细的说明。最后,将绘图函数用宏封装了起来,便于主程序中调用。当然,主程序中也可直接将参数压入堆栈。其实在较高版本的编译程序中,可以用PROTO伪指令定义函数原型,再用INVOKE伪指令调用。
注:本程序在WIN98系统下由MASM5.0编译通过,XP下好象不行。
.MODEL SMALL
.386
.STACK 100
.DATA
COLOR DW 02
BKCOLOR DW 15
RADIUS DW 45
;画点宏
MPIXEL MACRO X,Y,COLOR
PUSH X
PUSH Y
PUSH COLOR
CALL PIXEL
ENDM
;画线宏
MLINE MACRO X1,Y1,X2,Y2
PUSH X1
PUSH Y1
PUSH X2
PUSH Y2
CALL LINE
ENDM
;画矩形宏
MRECTANGLE MACRO X1,Y1,X2,Y2
MLINE X1,Y1,X1,Y2
MLINE X1,Y1,X2,Y1
MLINE X2,Y1,X2,Y2
MLINE X1,Y2,X2,Y2
ENDM
;画圆宏
MCIRCLE MACRO X,Y,R
PUSH X
PUSH Y
PUSH R
CALL CIRCLE
ENDM
.CODE
MAIN PROC FAR
START: MOV AX,@DATA
MOV DS,AX
MOV AX,0A000H
MOV ES,AX
MOV AX,0012H
INT 10H ;设置640*480*16图形模式
MOV AL,2
CALL SET_WRITE_MODE ;将写模式设为写模式2
MOV AX,BKCOLOR
CALL CLEAR ;将背景清成白色
MLINE 100,100,150,150
MLINE 300,100,250,150
MLINE 100,300,150,250 ;采用宏
PUSH 300
PUSH 300
PUSH 250
PUSH 250
CALL LINE ;直接调用画线函数
MRECTANGLE 100,100,300,300
MRECTANGLE 150,150,250,250
MCIRCLE 200,200,RADIUS
MOV AH,01H
INT 21H
MOV AX,4C00H
INT 21H
MAIN ENDP
;******************************************
;640*480*16模式下的画点函数
;******************************************
PIXEL PROC
PUSH BP
PUSH BX
PUSH CX
PUSH DS
MOV BP,SP
MOV AX,80
MOV BX,WORD PTR[BP+12] ;BX<=Y
MUL BX ;(DX:AX)<=80*Y
MOV BX,AX ;
MOV AX,WORD PTR[BP+14] ;AX<--X
MOV CL,8 ; | |
DIV CL ;AL<=商(X/8),AH<=余数(X%8) SP-> | |
MOV CL,AH ;CL<=AH | DS |<-BP
MOV AH,0 ; | CX |<-BP+2
ADD BX,AX ;BX(OFFSET)<=80*Y+X/8 | BX |<-BP+4
MOV AL,80H ; | BP |<-BP+6
SHR AL,CL ;AL(MASK)<=(80H>>CL) |返回地址|<-BP+8
PUSH AX ; | COLOR |<-BP+10
MOV DX,3CEH ; | Y |<-BP+12
MOV AL,8 ; | X |<-BP+14
OUT DX,AL ; | |
MOV DX,3CFH ; PIXEL堆栈结构
POP AX
OUT DX,AL
MOV AL,ES:[BX]
MOV AX,WORD PTR[BP+10] ;AX<=COLOR
MOV BYTE PTR ES:[BX],AL
POP DS
POP CX
POP BX
POP BP
RET 6
PIXEL ENDP
;******************************************
;Bresenham算法实现的画线函数
;******************************************
LINE PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,16
MOV WORD PTR[BP-6],0 ;X=0
MOV WORD PTR[BP-8],0 ;Y=0
MOV WORD PTR[BP-14],1 ;INCX=1
MOV WORD PTR[BP-16],1 ;INCY=1
MOV AX,WORD PTR[BP+6] ;AX<=X2
SUB AX,WORD PTR[BP+10] ;AX<=X2-X1
JNC L1 ;IF X2>=X1,JMP L1
NEG AX ;IF X2<X1,DELTA_X=-DELTA_X
MOV WORD PTR[BP-14],-1 ;INCX<=-1
L1: CMP AX,0 ;IF DELTA_X!=0,JMP L11
JNE L11 ;
MOV WORD PTR[BP-14],0 ;INCX<=0
L11: MOV WORD PTR[BP-10],AX ;DELTA_X<=AX SP-> | |
MOV AX,WORD PTR[BP+4] ;AX<=Y2 | INCY |
SUB AX,WORD PTR[BP+8] ;AX<=Y2-Y1 | INCX |<-BP-14
JNC L2 ;IF Y2>=Y1,JMP L2 | DELTA_Y|<-BP-12
NEG AX ;IF Y2<Y1,DELTA_Y=-DELTA_Y | DELTA_X|<-BP-10
MOV WORD PTR[BP-16],-1 ;INCY<=-1 | Y |<-BP-8
L2: CMP AX,0 ;IF DELTA_Y!=0,JMP L22 | X |<-BP-6
JNE L22 ; |DISTANCE|<-BP-4
MOV WORD PTR[BP-16],0 ;INCY<=0 | T |<-BP-2
L22: MOV WORD PTR[BP-12],AX ;DELTA_Y<=AX | BP |<-BP
LP4: MOV AX,WORD PTR[BP-10] ;AX<=DELTA_X |返回地址|<-BP+2
CMP AX,WORD PTR[BP-12] ; | Y2 |<-BP+4
JG LP5 ;DELTA_X>DELTA_Y | X2 |<-BP+6
MOV AX,WORD PTR[BP-12] ; | Y1 |<-BP+8
MOV WORD PTR[BP-4],AX ;DISTANCE<=DELTA_Y | X1 |<-BP+10
JMP LP51 ; | |
LP5: MOV AX,WORD PTR[BP-10] ; LINE堆栈结构
MOV WORD PTR[BP-4],AX ;DISTANCE<=DELTA_X
LP51: INC AX
MOV WORD PTR[BP-2],AX
LP6: PUSH WORD PTR[BP+10]
PUSH WORD PTR[BP+8]
PUSH COLOR
CALL PIXEL
MOV AX,WORD PTR[BP-6] ;AX<=X
ADD AX,WORD PTR[BP-10] ;AX<=X+DELTA_X
MOV WORD PTR[BP-6],AX ;X=X+DELTA_X
MOV AX,WORD PTR[BP-8] ;AX<=Y
ADD AX,WORD PTR[BP-12] ;AX<=Y+DELTA_Y
MOV WORD PTR[BP-8],AX ;Y=Y+DELTA_Y
MOV AX,WORD PTR[BP-6] ;AX<=X
CMP AX,WORD PTR[BP-4]
JLE LP7 ;IF X<=DISTANCE,JMP LP7
MOV AX,WORD PTR[BP-6] ;X>DISTANCE
SUB AX,WORD PTR[BP-4] ;AX<=X-DISTANCE
MOV WORD PTR[BP-6],AX ;X=X-DISTANCE
MOV AX,WORD PTR[BP+10] ;AX<=X1
ADD AX,WORD PTR[BP-14] ;AX<=X1+INCX
MOV WORD PTR[BP+10],AX ;X1=X1+INCX
LP7: MOV AX,WORD PTR[BP-8] ;AX<=Y
CMP AX,WORD PTR[BP-4]
JLE LP8 ;IF Y<=DISTANCE,JMP LP8
MOV AX,WORD PTR[BP-8] ;Y>DISTANCE
SUB AX,WORD PTR[BP-4] ;AX<=Y-DISTANCE
MOV WORD PTR[BP-8],AX ;Y=Y-DISTANCE
MOV AX,WORD PTR[BP+8] ;AX<=Y1
ADD AX,WORD PTR[BP-16] ;AX<=Y1+INCY
MOV WORD PTR[BP+8],AX ;Y1=Y1+INCY
LP8: DEC WORD PTR[BP-2] ;IF T!=0,JMP LP6
JZ LP9
JMP LP6
LP9: MOV SP,BP
POP BP
RET 8
LINE ENDP
;***************************************
;Bresenham算法实现的画圆函数
;***************************************
CIRCLE PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,6
MOV WORD PTR[BP-2],0 ;X<=0 | |
MOV AX,WORD PTR[BP+4] ; | |
MOV WORD PTR[BP-4],AX ;Y<=R SP-> | |
MOV AX,-2 ; | P |<-BP-6
IMUL WORD PTR[BP+4] ;AX<=RADIUS*(-2) | Y |<-BP-4
ADD AX,3 ;AX<=3-2*RADIUS | X |<-BP-2
MOV WORD PTR[BP-6],AX ;P=3-2*RADIUS | BP |<-BP
C0: MOV AX,WORD PTR[BP-2] ;AX<=X |返回地址|<-BP+2
CMP AX,WORD PTR[BP-4] ;IF X<Y,JMP C00 | RADIUS |<-BP+4
JL C00 ; | YC |<-BP+6
JMP C3 ; | XC |<-BP+8
C00: PUSH WORD PTR[BP+8] ; CIRCLE堆栈结构
PUSH WORD PTR[BP+6] ;
PUSH WORD PTR[BP-2]
PUSH WORD PTR[BP-4]
CALL CIRCLE_POINT
CMP WORD PTR[BP-6],0
JGE C1
MOV AX,4
MUL WORD PTR[BP-2]
ADD AX,6
ADD AX,WORD PTR[BP-6]
MOV WORD PTR[BP-6],AX
JMP C2
C1: MOV AX,WORD PTR[BP-2]
SUB AX,WORD PTR[BP-4]
MOV BX,4
IMUL BX
ADD AX,10
ADD AX,WORD PTR[BP-6]
MOV WORD PTR[BP-6],AX
DEC WORD PTR[BP-4]
C2: INC WORD PTR[BP-2]
JMP C0
C3: MOV AX,WORD PTR[BP-2]
CMP AX,WORD PTR[BP-4]
JNE C4
PUSH WORD PTR[BP+8]
PUSH WORD PTR[BP+6]
PUSH WORD PTR[BP-2]
PUSH WORD PTR[BP-4]
CALL CIRCLE_POINT
C4: MOV SP,BP
POP BP
RET 6
CIRCLE ENDP
CIRCLE_POINT PROC NEAR
PUSH BP
MOV BP,SP
SUB SP,16
MOV AX,WORD PTR[BP+10] ;
ADD AX,WORD PTR[BP+6] ;
MOV WORD PTR[BP-2],AX ;XC+X
MOV AX,WORD PTR[BP+10] ;
SUB AX,WORD PTR[BP+6] ;
MOV WORD PTR[BP-4],AX ;XC-X
MOV AX,WORD PTR[BP+10] ; | |
ADD AX,WORD PTR[BP+4] ; | |
MOV WORD PTR[BP-6],AX ;XC+Y | |
MOV AX,WORD PTR[BP+10] ; SP-> | |
SUB AX,WORD PTR[BP+4] ; | YC-Y |<-BP-16
MOV WORD PTR[BP-8],AX ;XC-Y | YC+Y |<-BP-14
MOV AX,WORD PTR[BP+8] ; | YC-X |<-BP-12
ADD AX,WORD PTR[BP+6] ; | YC+X |<-BP-10
MOV WORD PTR[BP-10],AX ;YC+X | XC-Y |<-BP-8
MOV AX,WORD PTR[BP+8] ; | XC+Y |<-BP-6
SUB AX,WORD PTR[BP+6] ; | XC-X |<-BP-4
MOV WORD PTR[BP-12],AX ;YC-X | XC+X |<-BP-2
MOV AX,WORD PTR[BP+8] ; | BP |<-BP
ADD AX,WORD PTR[BP+4] ; |返回地址|<-BP+2
MOV WORD PTR[BP-14],AX ;YC+Y | Y |<-BP+4
MOV AX,WORD PTR[BP+8] ; | X |<-BP+6
SUB AX,WORD PTR[BP+4] ; | YC |<-BP+8
MOV WORD PTR[BP-16],AX ;YC-Y | XC |<-BP+10
PUSH WORD PTR[BP-2] ; | |
PUSH WORD PTR[BP-14] ; CIRCLE_POINT堆栈结构
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-4]
PUSH WORD PTR[BP-14]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-2]
PUSH WORD PTR[BP-16]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-4]
PUSH WORD PTR[BP-16]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-6]
PUSH WORD PTR[BP-10]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-8]
PUSH WORD PTR[BP-10]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-6]
PUSH WORD PTR[BP-12]
PUSH COLOR
CALL PIXEL
PUSH WORD PTR[BP-8]
PUSH WORD PTR[BP-12]
PUSH COLOR
CALL PIXEL
MOV SP,BP
POP BP
RET 8
CIRCLE_POINT ENDP
;********************************
;清屏函数
;********************************
CLEAR PROC NEAR
MOV BX,0
CLR1: MOV ES:[BX],AL
INC BX
CMP BX,80*480
JNB CLR2
JMP CLR1
CLR2: RET
CLEAR ENDP
;********************************
;设置写模式的函数
;********************************
SET_WRITE_MODE PROC NEAR
PUSH AX
MOV DX,3CEH
MOV AL,5
OUT DX,AL
MOV DX,3CFH
POP AX
OUT DX,AL
MOV DX,3CEH
MOV AL,8
OUT DX,AL
MOV DX,3CFH
MOV AL,0FFH
OUT DX,AL
RET
SET_WRITE_MODE ENDP
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -