1、———————————————————作品声明—————————————————————— ; 1、本软件在emu8086平台下利用汇编语言编写调试完成,在WINDOWS XP SP3环境下全屏运行通过 ; 2、软件界面友好美观,操作方便,容错性强,程序模块化,高效易懂 ; 3、软件实现一个自定义图形(等腰直角三角形)的平移和旋转功能,进入软件后,主界面显示用 ; 户操作示意图,按任意键进入图形显示模式 ; 4、在图形显示模式下,按键'w','s','a','d'分别进行上下左右平移操作,平移步进值为单位坐标, ; 按键'j','k
2、'分别进行图形逆时针和顺时针操作,旋转步进值为15° ; 5、按键‘i'进入平移坐标值和旋转角度值的设定模式,根据提示进行输入,其中X轴方向的平移值 ; 以向右平移为正,向左为负;Y轴方向的平移值以向下平移为正,向上为负;旋转的角度值的输 ; 入值代表15°的倍数,以逆时针旋转为正,顺时针为负,如输入-2,代表顺时针旋转30°;输 ; 入以回车键进行确认,确认后,如果输入正确则立即刷新图形位置,否则重新输入或退出参数 ; 设定模式 ; 6、图形的移动范围被限制在浅蓝色矩形边框内,无法越界显示。 ; 7、在正常显示状
3、态下,用户键入回车键后,界面提示是否退出本软件的提示符,按键'y'和'n'分 ; 别进行确认或取消退出 ; 8、本代码仅供学习交流! ; 作者:Regal ; 日期:2014年 1月9日 ;———————————————————————————————————————————— ;include MyMacro.h
4、 ;*****************************宏文件包含********************************* ; MyMacro.inc - macro definitions defined by zhu zhengwei for easy input/output ; written date : 2014/1/5 ; —————— 声明 —————— ;以下创建一些程序中经常用到的功能的宏,其中一部分引用EMU8086环境内置宏文件emu8086.inc或 ;经本人修改后完成。为了省掉链接过
5、程,这里将该部分不另存为一个文件,而是直接包含在此。 ;*********************输出字符串****************** ; 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
6、 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,
7、0Eh ; teletype function. INT 10h JMP next_char printed: POP BX POP SI ; re-store registers... POP AX ; ENDM ;************************************************ ;*****************设置光标位置******************** ; sets current cursor ; position:
8、 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 ;***************************
9、 ;******************单字符的输出******************* ; 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
10、 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:
11、 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 ;
12、 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. M
13、OV 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 ;
14、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 ;
15、 POP AX ; RET CLEAR_SCREEN ENDP skip_proc_clear_screen: DEFINE_CLEAR_SCREEN ENDM ;************************************************************************* ;************************************************************************* data segment flag
16、 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 ? d
17、iffy2 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
18、 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
19、设置图形模式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-------------------
20、' 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) | Counterclockwis
21、e(J) Clockwise(K)|' GOTOXY 8,5 PRINT '| Down(S) | |' GOTOXY 8,6 PRINT '| | |' GOTOXY 8,7 PRINT '| You can enter the s
22、etting 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 '| |'
23、 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
24、 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
25、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 t
26、o 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
27、 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
28、 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 sho
29、w_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 ro
30、tateback 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 rotat
31、eback1 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 ;**************************************************** ;*******
32、交互输入参数值******************* 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
33、 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
34、 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 jud
35、gebx1 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 j
36、mp call_judge ninputa_error: ;输入无误,清楚入栈内容,防止占用空间 pop cx pop cx pop cx call show_figure jmp get_key ;********************************************** ;*****************数据输入函数***************** data_input proc push bx p
37、ush 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_ne
38、xt: 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
39、 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 buffe
40、r+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 ;********************************************** ;*
41、输入错误提示******************* 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 ;********************************************** ;************判断坐标点是否越界
42、的函数****************** 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
43、 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
44、 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
45、判断第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
46、 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:
47、 mov ax,0 mov flag,ax ;flag为0代表出界,为1代表不出界 pop di pop si pop ax pop dx ret judge_range endp ;***************************************************** ;**********************描点函数***********************
48、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
49、 pop bx pop ax ret draw_point endp ;**************************************************** ;*************Bresenham算法画直线******************** draw_line proc push si ;现场保护 push di push ax pu
50、sh 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






