回 帖 发 新 帖 刷新版面

主题:[原创]下面的程序想换个高效的算法,请赐教……!

;-------------------------------------------             
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个回复)

沙发

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
;------------------------------------

板凳

;清除两个小球的子程序

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 楼

;------------------------------------------------------      
;画球子程序
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 楼

急,请大家赶紧回帖啊
谢谢了

5 楼

这个是我在这个论坛看到的最好的程序,代码风格非常好,解释也恰到好处。
不过对于过程的参数传递的方法比较古老和麻烦,这个可以交给编译程序完成。
子过程的完整定义的具体完成细节可以去http://www.mdjx.net/course/hep/huibianyuyan/course.htm看看。
你在CSDN也发了帖子把,程序还没有看完,明天接着看,睡觉。

6 楼

直接对端口进行控制把,BOIS 10H的效率太低了。

我来回复

您尚未登录,请登录后再回复。点此登录或注册