您现在的位置: 捷凌网安 >> 编程语言 >> 汇编编程 >> 正文
套装软件制作(2)

作者:佚名 责任编辑:左决 点击数: 更新时间:2008-2-16 6:00:38

第三节  程式合并 

    我所见过的各种组合程式虽不算多,但至少有百余个了。毛病最多的当然是缺乏完整的规划,其次则是信马游缰,一份不折不扣的流水帐!明明大门口在东边,程式硬要朝西,直到游完了大观园,天黑了,才出东门! 
    这种程式我收集了一大叠,可是举来做例子,却心有余而力不足。原因无他,实在不耐烦照抄一遍,一见到就头痛! 
    电脑最强的功能,便是处理繁杂重复的工作,为什么一般程式师居然存心与电脑争风吃醋呢?不说别的,光把程式输入到电脑中,就要花上几个月宝贵的光阴,真值得这样做吗? 
    有一份程式,足足有四十多页,我只略作调整,便缩小到十页,处理速度则快了五倍。为什么会差这样远呢?很简单,有些人不喜欢用大脑,久而久之,习惯成自然,大脑就生了铁銹!除了等因奉此,什么都不会想了。 
    要想做一个优秀的程式师,第一个条件是不能偷懒,第二个条件则要有分析观察的习惯,第三个也是最重要的,则是要有追求完美的精神。程式师要像艺术家,不论是自己的或是别人的程式,都要一而再、再而三地玩味改良。 
    我曾见过一个扫地的妇人,她不管在哪里,见不得有任何脏乱。这种人才值得尊敬,这种精神是伟大的,与她的职业丝毫无关! 
    程式写得不够精简,有三个原因,第一个是程式师无能,这种程式能够写完,可以运行,已算相当难得了;第二个原因是不懂技巧,硬桥硬马的干, 不知什么是效率,也不知道如何达成。自己写的程式都不见得看得懂,遑论他人的?第三则是根本缺乏敬业精神,敷衍塞责,这种人我最瞧不起。 
    写程式之初,如果把任务瞭解清楚,然后分析因素,分割模组。所有类似的情况都合并到一处,再以变数代替,统一执行。这原本是份内的工作,前述的情况根本不可能发生! 
    问题是发生了以后怎么办呢?我建议最好重写,如果一定要改,只好采用程式合并的技巧,浓缩一下。 
    合并的目的是为了增进效率,而合并的方法则因情况不同而异,就像人生了病,必须先查出病因,否则无法下药。我试着以所知道的一些例证,简要地解说如后。 

一、过程的合并: 

    要做过程的合并,首先要查明下列各点: 
  1,首先找出过程类似的,全部移到一堆,如果找不到,那就没救了。 
    然而,这种程式要就是太小,根本不可能有类似的情况,再不就是写作时杂乱无章,信马游缰。分明有类似的过程,但没有共通的原则,无从浓缩。当然,也可能有些程式,因工作量及处理的细节太多,以致无法浓缩。 

  2,在类似的程式中,找寻相异的指令或流程,再若没有,那就是重复了,正宜合并。 

  3,把相异的指令或流程用变数取代,或将不同程式之入口放在暂存器里。 

  4,将各程式在应用该流程前,设好变数及使用的暂存器。 

  5,合并相似的程式段,不同处应用变数取代之。 

    下面举一实例,系一绘图程式之片断,兹改变原用标题,并将分散在各处若干不同之段,列述如下: 
  189: MASK    PROC    NEAR 
  190:        MOV    DX,3C4H 
  191:        MOV    AL,2 
  192:        OUT    DX,AL 
  193:        MOV    DX,3C5H 
  194:        MOV    AL,PCOLOR 
  195:        OUT    DX,AL 
  196:        RET 
  197: MASK    ENDP 
  … 
  380:        MOV    DX,03CEH 
  381:        MOV    AL,3 
  382:        OUT    DX,AL 
  383:        MOV    AL,18H 
  384:        INC    DX 
  385:        OUT    DX,AL 
  386:        RET 
  … 
  490:        MOV    DX,3CEH 
  491:        MOV    AL,3 
  492:        OUT    DX,AL 
  493:        MOV    DX,3CFH 
  494:        MOV    AL,0H 
  495:        OUT    DX,AL 
  496:        RET 
  … 
  589: CROSS    PROC    NEAR 
  590:        MOV    DX,3C4H 
  591:        MOV    AL,2 
  592:        OUT    DX,AL 
  593:        INC    DX 
  594:        MOV    AL,0FH 
  595:        OUT    DX,AL 
  596:        RET 
  597: CROSS    ENDP 
  … 

    这样的段落有十多处,看来每个都略有不同,似乎不能合并。然而仔细分析,显然是程式师训练不够,把一个非常有规则的程式,安排得非常紊乱,以致到这个地步。  
    我们先归纳问题,决定如何合并。第一,上述各段程式,应该统一作为子程式;第二,全部变数只有四个,其中两个是传送值,两个是输出入埠。后者有连续关系,等于只有一个。因此,在调用此子程式前,应先令DX为输出入埠,再将变数装入AX中,一次调用即可。此子程式如下: 
  300: SUB: 
  301:        OUT    DX,AL 
  302:        INC    DX 
  303:        MOV    AL,AH 
  304:        OUT    DX,AL 
  305:        RET 
    这样简短的子程式,有无必要,端视时空的效益而定。不论怎样整理,都远比原来的要好。 
    另外有种情况,更为可怕,就是在键盘输入后,用流程方式,一一比较输入码,再一一分别处理。 
    比如说,为了检查游标键的左、右、上、下等八个方向的移动,以便作相应的处理,程式居然写成: 
  100: PP1:    MOV    AH,0 
  101:        INT    16H 
  102:        CMP    AX,4800H    ;↑键 
  103:        JNE    NEXT1 
  104:        CALL    MOVDATA     ;SET BUFFERS 
  105:        CALL    SETDLT        ;SET INCREMENT 
  106: NXT01: 
  107:        CALL    DOTUP 
  108:        LOOP    NXT01 
  109:        CALL    XORDOT        ;SET NEW DOT 
  110:        CALL    XYDISP        ;DISP NEW XXX,YYY 
  111:        JMP    PP1 
  112: NEXT1: 
  113:        CMP    AX,5000H    ;↓键 
  114:        JNE    NEXT2 
  115:        CALL    MOVDATA     ;SET BUFFERS 
  116:        CALL    SETDLT        ;SET INCREMENT 
  117: NXT02: 
  118:        CALL    DOTDOWN 
  119:        LOOP    NXT02 
  120:        CALL    XORDOT        ;SET NEW DOT 
  121:        CALL    XYDISP        ;DISP NEW XXX,YYY 
  122:        JMP    PP1 
  123: NEXT2: 
  124:        CMP    AX,4B00H    ;←键 
  125:        JNE    NEXT3 
  … 
    这段程式总共要检查八次,才能确定是否有游标移动以及哪个游标在移动。然后,还要一一检查其他变化,共有十八种有效码。我实在佩服这种程式师,不但有无比的耐性,还有非凡的想像力,居然能把一段极为简单平凡的程式,写得这样的精彩动人! 
    如果是我,我会写得毫无趣味: 
  100: PP1:    SUB    AH,AH 
  101:        INT    16H 
  102:        OR    AL,AL 
  103:        JNZ    PP1        ;AL 非0无效 
  104:        MOV    BH,AL 
  105:        MOV    BL,AH 
  106:        SUB    BL,47H        ;最小之字标键 
  107:        JLE    PP1        ;非处理范围 
  108:        SHL    BX,1 
  109:        CALL    FUNC[BX] 
  110:        JMP    PP1 
    这是主流程,程式短,速度快,维护容易,一眼看过去,有什么错误立刻分明。 
 … 
 1000: FUNC    DW    NEXT02        ;↖ 
 1001:        DW    NEXT0        ;↑ 
 1002:        DW    NEXT04        ;↗ 
 1003:        DW    PPRET        ;无效 
 1004:        DW    NEXT2        ;← 
 1005:        DW    PPRET        ;无效 
 1006:        DW    NEXT4        ;→ 
 1007:        DW    PPRET       ;无效 
 1008:        DW    NEXT12        ;↙ 
 1009:        DW    NEXT1        ;↓ 
 1010:        DW    NEXT14        ;↘ 
 … 
    因为这是子程式,加一段、减一段容易非常。 
    即使是子程式,也有很大的考究,就以前段来说,在 104至110 之间,就值得三思。 
  104:        CALL    MOVDATA     ;SET BUFFERS 
  105:        CALL    SETDLT        ;SET INCREMENT 
  106: NXT01: 
  107:        CALL    DOTUP 
  108:        LOOP    NXT01 
  109:        CALL    XORDOT        ;SET NEW DOT 
  110:        CALL    XYDISP        ;DISP NEW XXX,YYY 
    首先,104 和105 会重复多次,109 及110 亦然,为什么不合并为一呢?这也是很常见的程式合并手法,两次调用合为一次,速度及空间都较为经济。 
    在子程式 SETDLT 之前,先调用一次 MOVDATA,另XYDISP也是一样,首先备妥: 
 3000: SETDATA: 
 3001:        CALL    MOVDATA     ;假设本程式有他用 
 3002: SETDLT: 
 3003:          … 
 … 
 3100: XYDIDOT: 
 3101:        CALL    XORDOT        ; 同上 
 3102: XYDISP: 
 3103:        … 
 … 
    再来设计NEXT0 的子程式: 
  110: NEXT0: 
  111:        CALL    SETDATA 
  112: NXT01: 
  113:        DOTUP  应搬至此,无需设为子程式。 
  … 
  120:        LOOP    NXT01 
  121:        JMP    XYDIDOT     ; 如有必要,可先 
                                    ; 设好参数 
    这样合并一下,效果决不止高上十倍,等到真正学会了程式的技巧,写作时速度也可以提高数倍。

[1] [2] 下一页

  • 上一篇文章:

  • 下一篇文章:
  •  
    最进更新
    普通文章VC++设计超强仿QQ自动伸缩窗04-17
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    普通文章多线程、Socket技术及委托技04-11
    推荐文章VB.Net连接各种数据库的几种04-11
    普通文章VB.NET中的多窗体编程:升级04-11
    普通文章用VB.NET定制Windows控件04-11
    普通文章VB.NET中监视文件夹的变化04-11
    普通文章VB.NET中对象的克隆04-11
    推荐文章VB.NET中的TextBox控件详解04-11
     
    推荐文章
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    推荐文章VB.Net连接各种数据库的几种04-11
    推荐文章VB.NET中的TextBox控件详解04-11
    推荐文章在VB.NET中进行抓屏04-11
    推荐文章VB.Net开发的长内容自动分页04-11
    推荐文章VB.NET中快速访问注册表技巧04-11
    推荐文章PHP5手动最简安装方法03-07
    推荐文章完全讲解PHP+MySQL的分页显示03-07
    推荐文章Linux Shell元字符知识笔记02-21
     
    热点文章 
    普通文章VC++设计超强仿QQ自动伸缩窗04-17
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    普通文章VB.NET中的多窗体编程:升级04-11
    普通文章用VB.NET定制Windows控件04-11
    普通文章VB.NET中对象的克隆04-11
    推荐文章VB.NET中的TextBox控件详解04-11
    普通文章VB/VB.NET/C#导出到Excel的方04-11
    普通文章如何通过VB.NET获取网卡地址04-11
    普通文章VB.NET中使用ListView控件的04-11

    | 设为首页 | 加入收藏 | 联系站长 | 广告服务 | 友情链接 | 版权申明 | 网站地图 |

    在线交流 捷凌网安主群:51649627
    Copyright 2007-2008 © 捷凌网安. All rights reserved.
    备案序号:蜀ICP备08001812号