主题:[原创]下面的程序想换个高效的算法,请赐教……!
flycooler
[专家分:0] 发布于 2006-06-15 20:22:00
;-------------------------------------------
STACK1 SEGMENT PARA STACK ;定义堆栈段
DW 50 DUP(?)
STACK1 ENDS
;---------------------------------------------
DATA SEGMENT
SINE DW 00, 02, 03, 05, 07, 09, 11, 12, 14, 16 ;SINE函数表
DW 17, 19, 21, 23, 24, 26, 28, 29 ,31, 33
DW 34, 36, 37, 39, 41, 42, 44, 45, 47, 49
DW 50, 52, 53, 54, 56, 57, 59, 60, 62, 63
DW 64, 66, 67, 68, 69, 71, 72, 73, 74, 75
DW 77, 78, 79, 80, 81, 82, 83, 84, 85, 86
DW 87, 87, 88, 89, 90, 91, 91, 92, 93, 93
DW 94, 95, 95, 96, 96, 97, 97, 97, 98, 98
DW 98, 99, 99, 99, 99, 100, 100, 100, 100
DW 100, 100 ;放大100 倍的sin0 -sin90
MM DW ? ;存放结果的暂存空间
F_MM DW ? ;同上
NN DW ? ;同上
F_NN DW ? ;同上
SSP DW ? ;同上
KK DW 100 ;放大倍数
COUNT DB 90 ;角度大小
R DW ? ;暂存空间
OY DW ? ;存放球心纵坐标的暂存空间
OX DW ? ;存放球心横坐标的暂存空间
RR DW ? ;存放半径暂存空间
COLOR DW ? ;暂存空间
回复列表 (共6个回复)
沙发
flycooler [专家分:0] 发布于 2006-06-15 20:24:00
SMALL1_Y DW 320 ;小球1球心纵坐标
SMALL1_X DW 100 ;小球1球心横坐标
SMALL1_R DW 15 ;小球1半径大小
SMALL2_X DW 500 ;小球2球心横坐标
SMALL2_R DW 15 ;小球2半径大小
BIG_X DW 300 ;大球横坐标
BIG_Y DW 300 ;大球纵坐标
BIG_R DW 30 ;大球半径
BIG_COLOR DW 1 ;大球颜色
CLEAR_COLOR DW 0 ;擦除颜色即黑色
SMALL_COLOR DW 4 ;小球颜色
ESCAPE EQU 1BH ;定义esc键
ENTERR EQU 0DH ;定义enter键
DATA ENDS
;--------------------------------------------
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK1
;--------------------------------------
;程序开始
BEG: MOV AX, DATA
MOV DS, AX
CALL SCREEN ;设置屏幕工作方式
CALL DRAW_SMALL ;调用画大球子程序
CALL DEAW_BIG ;调用画大球子程序
RESTART:
MOV AH, 0 ;等待用户输入
INT 16H
CMP AL, ESCAPE ;比较输入
JE EXIT ;当输入为esc键时退出
CMP AL, ENTERR ;比较输入
JNE EXIT ;当输入不是回车键时退出
EASE: CALL CLEAR_SMALL ;调用擦除小球子程序
ADD SMALL1_X, 5 ;将其球心坐标移位
SUB SMALL2_X, 5
CMP SMALL1_X, 255;判断是否与大球相撞
JE MUSI ;相撞则发声
JMP NEXT1
MUSI: CALL MUSIC ;调用发声子程序
NEXT1: CMP SMALL1_X, 255 ;判断是否撞到大球
JE SPRING ;若相撞则跳转到弹起程序段
CALL DRAW_SMALL ;否则调用画小球子程序重绘两个小球
JMP EASE ;跳转到擦除程序段擦除两个小球
SPRING: ;大球弹起,小球从两边向中间运动
CALL CLEAR_SMALL ;调用擦除小球子程序
CALL CLEAR_BIG ;调用擦除大球子程序
ADD SMALL2_X, 5 ;改变小球圆心坐标
SUB SMALL1_X, 5 ;同上
SUB BIG_Y, 5 ;改变大球圆心纵坐标
CALL DRAW_SMALL ;调用画小球子程序,两小球同时向两边
CALL DEAW_BIG ;调用画大球子程序,大球向上弹起
CMP SMALL1_X, 100 ;判断小球运动位置
JE DOWN ;当两个小球运动到边上则跳转到大球下落程序段
JMP SPRING
DOWN: ;大球下降标记
CALL CLEAR_BIG ;调用擦除大球子程序擦除大球
ADD BIG_Y, 5 ;增加大球y坐标即大球开始下落
CALL DEAW_BIG ;调用画大球子程序
CMP BIG_Y, 300 ;如果移到一定位置则跳转到重新开始处
JNA DOWN
JMP RESTART
EXIT: ;退出
MOV AX, 2
INT 10H
MOV AH, 4CH
INT 21H
;------------------------------------
板凳
flycooler [专家分:0] 发布于 2006-06-15 20:27:00
;清除两个小球的子程序
CLEAR_SMALL PROC
PUSH SMALL1_X ;将小球1各参数压入栈
PUSH SMALL1_Y
PUSH SMALL1_R
PUSH CLEAR_COLOR
CALL DRAW_P ;调用擦除子程序擦除小球1
PUSH SMALL2_X ;将小球2各参数压入栈
PUSH SMALL1_Y
PUSH SMALL2_R
PUSH CLEAR_COLOR
CALL DRAW_P ;调用擦除子程序擦除小球2
RET
CLEAR_SMALL ENDP
;---------------------------------------
;清除大球的子程序
CLEAR_BIG PROC
PUSH BIG_X ;将大球各参数压入栈
PUSH BIG_Y
PUSH BIG_R
PUSH CLEAR_COLOR
CALL DRAW_P ;调用擦除子程序清除大球
RET
CLEAR_BIG ENDP
;----------------------------------------
;画小球子程序
DRAW_SMALL PROC
PUSH SMALL1_X ;将小球1各参数压入栈
PUSH SMALL1_Y
PUSH SMALL1_R
PUSH SMALL_COLOR
CALL DRAW_P ;调用画球子程序画小球1
PUSH SMALL2_X ;将小球2各参数压入栈
PUSH SMALL1_Y
PUSH SMALL2_R
PUSH SMALL_COLOR
CALL DRAW_P ;调用画球子程序画小球2
RET
DRAW_SMALL ENDP
;------------------------------------
;画大球子程序
DEAW_BIG PROC
PUSH BIG_X ;将小球2各参数压入栈
PUSH BIG_Y
PUSH BIG_R
PUSH BIG_COLOR
CALL DRAW_P ;调用画球子程序画大球
RET
DEAW_BIG ENDP
;-----------------------------------------------------
;发声子程序
MUSIC PROC
IN AL, 61H ;读PB口当前状态
OR AL, 00000011B ;使PBI,PB0均为1
OUT 61H, AL ;写新的PB口值,接通扬声器
MOV DX, 12H
MOV AX, 34DEH
MOV CX, 120 ;频率值
DIV CX ;计数初值->AX
OUT 42H, AL ;写低8位
MOV AL, AH
OUT 42H, AL ;写高8位
WAIT01: MOV CX, 2000 ;设定延时间
LONG: LOOP LONG
DEC BX
JNZ WAIT01
IN AL, 61H ;读PB口当前状态
AND AL, 11111100B ;使PBI,PN0均为0
OUT 61H, AL ;扬声器停止工作
RET
MUSIC ENDP
;----------------------------------------------
COMPUTE PROC
MOV AX, [SI]
MUL R
DIV KK ;(函数值*rr)/kk即相对与球心坐标y象素需要改变的量
MOV MM, AX ;将结果放入mm中
NEG AX ;求其负数将它放入f-mm中
MOV F_MM, AX
MOV AX, [DI]
MUL R ;半径大小
DIV KK
MOV NN, AX
NEG AX
MOV F_NN, AX
RET
COMPUTE ENDP
3 楼
flycooler [专家分:0] 发布于 2006-06-15 20:28:00
;------------------------------------------------------
;画球子程序
WRITE PROC
MOV DX, F_MM
ADD DX, OY
MOV CX, NN
ADD CX, OX ;球心坐标
CALL WR_DOT ;画一象限的点
MOV CX, F_NN
ADD CX, OX
CALL WR_DOT ;画二象限的点
MOV DX, MM
ADD DX, OY
CALL WR_DOT ;画三象限的点
MOV CX, NN
ADD CX, OX
CALL WR_DOT ;画四象限的点
RET
WRITE ENDP
;----------------------------------------------------
WR_DOT PROC ;写象素dx为行cx为列
MOV AH, 0CH
MOV AL, BYTE PTR COLOR
MOV BH, 0
INT 10H
RET
WR_DOT ENDP
;----------------------------------------------------
SCREEN PROC ;设置屏幕工作方式
;设置为640*480 彩色图形
MOV AX, 12H
INT 10H
MOV AH, 0BH ;设置背景色为黑色
MOV BX, 0
INT 10H
RET
SCREEN ENDP
;----------------------------------------------------
;擦除子程序
DRAW_P PROC
POP SSP
POP COLOR
POP RR
POP OY
POP OX
MOV COUNT, 90
MOV SI, OFFSET SINE +89*2 ;倒查sin表
MOV DI, OFFSET SINE
MOV DX, RR
MOV R, DX
SPOP:
MOV COUNT , 90
MOV SI, OFFSET SINE +89*2 ;倒查sin表
MOV DI, OFFSET SINE
AGA:
CALL COMPUTE
CALL WRITE
SUB SI, 2
ADD DI, 2
DEC COUNT
JNZ AGA
SUB R,1
JNZ SPOP
PUSH SSP
RET
DRAW_P ENDP
;-----------------------------------------------------
CODE ENDS
END BEG
上面的实现运动的小球的算法太烦琐了,我用的其他的算法可惜就是没实现,请高手赐教!……
4 楼
flycooler [专家分:0] 发布于 2006-06-15 20:47:00
急,请大家赶紧回帖啊
谢谢了
5 楼
chenzep [专家分:3640] 发布于 2006-06-16 01:01:00
这个是我在这个论坛看到的最好的程序,代码风格非常好,解释也恰到好处。
不过对于过程的参数传递的方法比较古老和麻烦,这个可以交给编译程序完成。
子过程的完整定义的具体完成细节可以去http://www.mdjx.net/course/hep/huibianyuyan/course.htm看看。
你在CSDN也发了帖子把,程序还没有看完,明天接着看,睡觉。
6 楼
chenzep [专家分:3640] 发布于 2006-06-16 11:32:00
直接对端口进行控制把,BOIS 10H的效率太低了。
我来回复