资源描述
;———————————————————作品声明——————————————————————
; 1、本软件在emu8086平台下利用汇编语言编写调试完成,在WINDOWS XP SP3环境下全屏运行通过
; 2、软件界面友好美观,操作方便,容错性强,程序模块化,高效易懂
; 3、软件实现一个自定义图形(等腰直角三角形)的平移和旋转功能,进入软件后,主界面显示用
; 户操作示意图,按任意键进入图形显示模式
; 4、在图形显示模式下,按键'w','s','a','d'分别进行上下左右平移操作,平移步进值为单位坐标,
; 按键'j','k'分别进行图形逆时针和顺时针操作,旋转步进值为15°
; 5、按键‘i'进入平移坐标值和旋转角度值的设定模式,根据提示进行输入,其中X轴方向的平移值
; 以向右平移为正,向左为负;Y轴方向的平移值以向下平移为正,向上为负;旋转的角度值的输
; 入值代表15°的倍数,以逆时针旋转为正,顺时针为负,如输入-2,代表顺时针旋转30°;输
; 入以回车键进行确认,确认后,如果输入正确则立即刷新图形位置,否则重新输入或退出参数
; 设定模式
; 6、图形的移动范围被限制在浅蓝色矩形边框内,无法越界显示。
; 7、在正常显示状态下,用户键入回车键后,界面提示是否退出本软件的提示符,按键'y'和'n'分
; 别进行确认或取消退出
; 8、本代码仅供学习交流!
; 作者:Regal
; 日期:2014年 1月9日
;————————————————————————————————————————————
;include MyMacro.h
;*****************************宏文件包含*********************************
; MyMacro.inc - macro definitions defined by zhu zhengwei for easy input/output
; written date : 2014/1/5
; —————— 声明 ——————
;以下创建一些程序中经常用到的功能的宏,其中一部分引用EMU8086环境内置宏文件emu8086.inc或
;经本人修改后完成。为了省掉链接过程,这里将该部分不另存为一个文件,而是直接包含在此。
;*********************输出字符串******************
; this macro prints a string that is given as a parameter, example:
; PRINT 'hello world!'
; new line is NOT added.
PRINT MACRO sdat
LOCAL next_char, s_dcl, printed, skip_dcl
PUSH AX ; store registers...
PUSH SI ;
PUSH BX
JMP skip_dcl ; skip declaration.
s_dcl DB sdat, 0
skip_dcl:
LEA SI, s_dcl
MOV BX,3
next_char:
MOV AL, CS:[SI]
CMP AL, 0
JZ printed
INC SI
MOV AH, 0Eh ; teletype function.
INT 10h
JMP next_char
printed:
POP BX
POP SI ; re-store registers...
POP AX ;
ENDM
;************************************************
;*****************设置光标位置********************
; sets current cursor
; position:
GOTOXY MACRO col, row
PUSH AX
PUSH BX
PUSH DX
MOV AH, 02h
MOV DH, row
MOV DL, col
MOV BH, 0
INT 10h
POP DX
POP BX
POP AX
ENDM
;************************************************
;******************单字符的输出*******************
; this macro prints a char in AL and advances
; the current cursor position:
PUTC MACRO char
PUSH AX
PUSH BX
MOV BX,01
MOV AL, char
MOV AH, 0Eh
INT 10h
POP BX
POP AX
ENDM
;************************************************
;*********************清屏函数 ******************
; this macro defines procedure to clear the screen,
; (done by scrolling entire screen window),
; and set cursor position to top of it:
DEFINE_CLEAR_SCREEN MACRO
LOCAL skip_proc_clear_screen
; protect from wrong definition location:
JMP skip_proc_clear_screen
CLEAR_SCREEN PROC NEAR
PUSH AX ; store registers...
PUSH DS ;
PUSH BX ;
PUSH CX ;
PUSH DI ;
MOV AX, 40h
MOV DS, AX ; for getting screen parameters.
MOV AH, 06h ; scroll up function id.
MOV AL, 0 ; scroll all lines!
MOV BH, 10H ; attribute for new lines.
MOV CH, 0 ; upper row.
MOV CL, 0 ; upper col.
MOV DI, 84h ; rows on screen -1,
MOV DH, [DI] ; lower row (byte).
MOV DI, 4Ah ; columns on screen,
MOV DL, [DI]
DEC DL ; lower col.
INT 10h
; set cursor position to top
; of the screen:
MOV BH, 0 ; current page.
MOV DL, 0 ; col.
MOV DH, 0 ; row.
MOV AH, 02
INT 10h
POP DI ; re-store registers...
POP CX ;
POP BX ;
POP DS ;
POP AX ;
RET
CLEAR_SCREEN ENDP
skip_proc_clear_screen:
DEFINE_CLEAR_SCREEN ENDM
;*************************************************************************
;*************************************************************************
data segment
flag dw 0 ;临时标志位
tempchar db 0,0,0
ten db 10
ten1 dw 10
buffer db 5,?,5 dup(0) ;用于AH=0AH, INT 21H功能的缓冲区,存放输入数据
x1 dw ?
y1 dw ?
x2 dw ?
y2 dw ?
diffx dw ?
diffy dw ?
diffx2 dw ?
diffy2 dw ?
incx dw ?
incy dw ?
;用于计算旋转角度的三角函数表
cosdx dw 100,97,87,71,49,24,0,-24,-49,-71,-87,-97,-100,-97,-87,-71,-49,-24,0,24,49,71,87,97
sindx dw 0,-24,-49,-71,-87,-97,-100,-97,-87,-71,-49,-24,0,24,49,71,87,97,100,97,87,71,49,24
data ends
stack segment
dw 128 dup(0) ;堆栈,主要用于保护现场和函数参数传递
stack ends
codes segment
assume cs:codes,ds:data,ss:stack
;***************正式程序段**********************
start:
DEFINE_CLEAR_SCREEN
mov ax, data
mov ds, ax ;数据段和附加段同段
mov es, ax
mov al,12h ;设置图形模式640*480*16S
mov ah,0
int 10h
mov ah,0bh ;设置背景色
mov bh,0
mov bl,7ch
int 10h
GOTOXY 38,0 ;设置光标位置
PUTC 02
PUTC 02
PUTC 02
GOTOXY 8,1
PRINT '|-_-------------------------WELCOME-----------------------------_-|'
GOTOXY 8,2
PRINT '| Move or rotate the figure as the following tips |'
GOTOXY 8,3
PRINT '| Up(W) | Rotate |'
GOTOXY 8,4
PRINT '| Left(S) Right(D) | Counterclockwise(J) Clockwise(K)|'
GOTOXY 8,5
PRINT '| Down(S) | |'
GOTOXY 8,6
PRINT '| | |'
GOTOXY 8,7
PRINT '| You can enter the setting mode when you input 'i',then you |'
GOTOXY 8,8
PRINT '| can set the parameters each time with a 'enter' key ended. |'
GOTOXY 8,9
PRINT '| |'
GOTOXY 8,10
PRINT '|-_----------------- REGAL ALL RIGHTS RESERVED-----------------_-|'
GOTOXY 2,11
PRINT 'PRESS ANYKEY TO SHOW THE FIGURE...(YOU CAN EXIT ANYTIME WHEN YOU INPUT ENTER.)'
GOTOXY 5,5
mov si,200
mov di,200
mov ah,8
int 21h
xor bx,bx
jmp press_w
get_key:
mov ah,8 ;识别按键,进入对应的处理过程
int 21h
cmp al,'w'
je press_w
cmp al,'s'
je press_s
cmp al,'a'
je press_a
cmp al,'d'
je press_d
cmp al,'j'
je press_j
cmp al,'k'
je press_k
cmp al,27
cmp al,'i'
je press_i
cmp al,0dh
je quit_
jmp get_key
; je press_esc
quit_: ;按回车键退出系统时设置提示符确认,防止误操作退出系统
GOTOXY 4,8
PRINT 'Do you want to exit? '
GOTOXY 4,9
PRINT 'Input y to exit, and input n to cancel...'
chooseexit:
mov ah,8
int 21h
cmp al,'y' ;按y确认退出,按n取消退出,过滤其它输入
je exit_system
cmp al,'n'
je cancel_exit
jmp chooseexit
cancel_exit:
call show_figure
jmp get_key
exit_system:
mov ax, 4c00h ;程序返回操作系统
int 21h
;*************上下左右平移和旋转操作**************
press_w:
dec di
call judge_range ;移动图形之前,先判断是否移出界
mov ax,flag
cmp ax,1
jnz go_w
call show_figure
jmp get_key
go_w:
inc di
jmp get_key
press_s:
inc di
call judge_range
mov ax,flag
cmp ax,1
jnz go_s
call show_figure
jmp get_key
go_s:
dec di
jmp get_key
press_a:
dec si
call judge_range
mov ax,flag
cmp ax,1
jnz go_a
call show_figure
jmp get_key
go_a:
inc si
jmp get_key
press_d:
inc si
call judge_range
mov ax,flag
cmp ax,1
jnz go_d
call show_figure
jmp get_key
go_d:
dec si
jmp get_key
press_j:
cmp bx,44
jna rotateback
mov bx,-2
rotateback:
inc bx ;BX自增2,寻址三角函数表
inc bx
call judge_range
mov ax,flag
cmp ax,1
jnz go_j
call show_figure
jmp get_key
go_j:
dec bx
dec bx
jmp get_key
press_k:
cmp bx,2
jnl rotateback1
mov bx,48
rotateback1:
dec bx
dec bx
call judge_range
mov ax,flag
cmp ax,1
jnz go_k
call show_figure
jmp get_key
go_k:
inc bx
inc bx
jmp get_key
;****************************************************
;*******************交互输入参数值*******************
press_i:
push bx
push di
push si
GOTOXY 60,2 ;用':'指示对应位置的输入
PRINT ': '
call data_input
cmp ax,000fh ;键入'o'代表退出参数设定模式
jnz goon1
pop si ;输入有误,恢复表征坐标和角度的寄存器值
pop di
pop bx
call show_figure
jmp get_key
goon1:
add si,ax
call judge_range
mov ax,flag
cmp ax,1
jz ninputx_error
pop si
pop di
pop bx
jmp input_error
ninputx_error:
GOTOXY 60,3
PRINT ': '
call data_input
add di,ax
call judge_range
mov ax,flag
cmp ax,1
jz ninputy_error
pop si
pop di
pop bx
jmp input_error
ninputy_error:
GOTOXY 60,4
PRINT ': '
call data_input
shl ax,1
add bx,ax
cmp bx,46
jg judgebx
cmp bx,0
jl judgebx1
call_judge:
call judge_range
mov ax,flag
cmp ax,1
jz ninputa_error
pop si
pop di
pop bx
jmp input_error
judgebx:
sub bx,48
cmp bx,46
jg judgebx
jmp call_judge
judgebx1:
add bx,48
cmp bx,0
jl judgebx1
jmp call_judge
ninputa_error: ;输入无误,清楚入栈内容,防止占用空间
pop cx
pop cx
pop cx
call show_figure
jmp get_key
;**********************************************
;*****************数据输入函数*****************
data_input proc
push bx
push cx
push dx
lea dx,buffer
mov ah,0Ah
int 21h
mov ax,0
xor cx,cx
mov cl,buffer+1 ;系统自动载入,实际字符个数(不包括return)
lea bx,buffer+2
cmp [bx],'-'
jz data_next1 ;判断输入的是否为负数
data_next:
mul ten1 ;输入的字符转换为十六进制数放在AX中
mov dl,[bx]
and dl,0fh
add al,dl
adc ah,0
inc bx
loop data_next
jmp datainput_exit
data_next1:
dec cl
inc bx
data_next2:
mul ten1 ;输入代表负数,将输入数据求补后放在AX中
mov dl,[bx]
and dl,0fh
add al,dl
adc ah,0
inc bx
loop data_next2
neg ax
datainput_exit:
mov cl,0 ;及时清空缓存区
mov buffer+1,cl
mov buffer+2,cl
mov buffer+3,cl
mov buffer+4,cl
mov buffer+5,cl
mov buffer+6,cl
pop dx
pop cx
pop bx
ret
data_input endp
;**********************************************
;***************输入错误提示*******************
input_error:
call show_figure
GOTOXY 7,5
PRINT 'Input error,try again...(You can input 'o' to exit the setting mode)'
jmp press_i
;**********************************************
;************判断坐标点是否越界的函数******************
judge_range proc
push dx
push ax
push si
push di
;判断第1个顶点是否出界
mov dx,si
add dx,100
cmp dx,20
jng nshow_exit ;注意是用有符号数比较
cmp dx,620
jnl nshow_exit
mov dx,di
add dx,100
cmp dx,100
jng nshow_exit
cmp dx,470
jnl nshow_exit
;判断第2个顶点是否出界
mov dx,si
mov ax,[bx+cosdx]
add ax,100
add dx,ax
cmp dx,20
jng nshow_exit
cmp dx,620
jnl nshow_exit
mov dx,di
mov ax,[bx+sindx]
add ax,100
add dx,ax
cmp dx,100
jng nshow_exit
cmp dx,470
jnl nshow_exit
;判断第3个顶点是否出界
mov dx,si
mov ax,[bx+sindx]
neg ax
add ax,100
add dx,ax
cmp dx,20
jng nshow_exit
cmp dx,620
jnl nshow_exit
mov dx,di
mov ax,[bx+cosdx]
add ax,100
add dx,ax
cmp dx,100
jng nshow_exit
cmp dx,470
jnl nshow_exit
mov ax,1
mov flag,ax ;flag作为坐标点是否出界的标志
pop di
pop si
pop ax
pop dx
ret
nshow_exit:
mov ax,0
mov flag,ax ;flag为0代表出界,为1代表不出界
pop di
pop si
pop ax
pop dx
ret
judge_range endp
;*****************************************************
;**********************描点函数***********************
draw_point proc
push ax
push bx
push cx
push dx
mov ah,0ch
xor bx,bx
mov cx,si
mov dx,di
mov al,01h ;LINE ATTRIBUTE
int 10h ;画像素点
pop dx
pop cx
pop bx
pop ax
ret
draw_point endp
;****************************************************
;*************Bresenham算法画直线********************
draw_line proc
push si ;现场保护
push di
push ax
push bx
push cx
mov si,x1 ;画线起点
mov di,y1
call draw_point
mov incx,1
mov incy,1
mov ax,y2
cmp ax,y1
jz draw_horline
mov ax,x2
cmp ax,x1
展开阅读全文