组合语言之艺术
第四节 程序规划

  程序规划是指在整体设计的观念上,事先对全部程序周详地、有系统地分析,再定
出一个明晰的架构,以便于制作。
    最理想的方式,是从使用者的角度,先决定应用功能、用键、输入形式、空间结构
及模块划分等。
    这些都确定了,才能按图索骥,根据蓝图写程序。也就是说,规划即先把目标介定
妥当,以便按步就班,循序执行。
  1,工作的认识:程序的规划,相当于设计建筑篮图,首先要明确认识工作性质、特征、
条件,选择取适当的方式,以求得到最理想的结果。
  2,程序的结构:结构要事先定案,是采用流程抑或模块?全部或部份采用汇编语言?
是依工作人员的素质分工,或者是用生产线统一制作?程序段、数据段及堆栈段的空间
分配,每个程序联接次序的安排,寄存器的定义,缓冲器的设置等,都应该慎重地考虑
清楚,并记录下来,以供工作之依据。
  3,参数的设定:参数是程序的处理对象,必须合情合理地安排,且要有扩充的余地。
因为参数与功能分类及程序的效率息息相关,对程序员而言,参数即相当于程序的处理
对象;对应用程序的人,则等于工作的分类标准。其安排的结果,影响功能价值甚钜。
  4,效率的要求:在第一章第三节中,我们特别强调了效率的法则,使用计算机的目的,
就在于效率的追求。故在规划之初,就应该规定每一段程序的效率要求。
 另外,参数的运用,也应考虑其使用的频率,凡能在事先一次准备妥当的,切不可等到
运用时再临时计算。
  5,测试的标准:测试就是品质管理,程序所应达到的指针,可由测试求证之。一般程
序员只对程序的正确性负责。其实正确性与指针无关,乃是程序员最起码的责任。
 汇编程序的品质,应该包括原程序的写作规格及时限;程序的思路、理念;执行时的时
效;程序空间的大小及安排;应用的方便与否;指令运用是否恰当等等。
 执行程序的品管,则可以透过测试程序完成之。这种测试程序,也应该在规划之初,一
并考虑。
  6,制作的进度:程序制作的进度很难控制,而正因为其难以控制,更要加倍小心,事
先规划。其方法是先按照工作性质,设定工作「难度值」。再对工作的程序员评估其
「能力值」,依此设定一个「合理」的进度。最后,根据实际的工作进度调整之。一般
说来,程序员需要三年以上的写作经验,才能养成进度的观念。
    由于程序本身占有空间,所以其结构的好坏,对程序制作及执行效率影响极大。良
好的结构应根据程序的性质、使用的频率、处理的先后过程等,在效率的立场,作全面
的考虑。
一、程序性质
    前文曾介绍过程序的种类,在规划时,要更进一步了解程序的性质。因为所谓的效
率,一是指程序的制作、维护,一是指程序的执行及调用。这两者必须根据程序的性质,
作适当的安排。
    大体说来,程序的性质只有两种,一种是主动的,使用者可以直接控制执行;另一
种是被动的、公用的,为其它程序所调用。
    前者也可以说是应用程序,而后者比较类似系统程序。只是在这里强调的是其性质,
以及如何根据其性质进行规划。
    主动程序最好能放在同一模块中,当程序太大,必须分割时,也要设法联接在一起。
但若在功能不同,所调用的模块亦无交集的情况下,为了避免跨越段与段时的效率损失,
则无须考虑是否安置在同一模块内。
    由于主动程序涉及使用人的习惯和设计者的理念,经常需要修改调整,变动极大。
正因为这种因素,其「再利用」价值不高,对效率的要求也较低。
    规划时,主动程序一定要与被动程序分开,而在制作时,则应注意其所占用的空间,
与各段的关系。
    被动程序既然是公用的,必然具备一些基本的功能。所谓被动是表示该程序仅在某
种条件下,才被调用。由于其「再利用」的特色,应该设计成为精简的子程序。再依情
况需要,或者为了节省空间,放在磁盘中,随时以覆盖其它子程序方式调用,或者为了
效率,直接联接备用。
二、使用频率
    对程序执行的效率而言,占用空间与处理时间,经常需要作些取舍。如果程序太大,
空间不敷应用,则在规划时,先行统计各个程序的使用频率。
    不常用到的程序,不表示并不重要,但若占用了空间,则于效率有损。
    这种程序最好独立成一个模块,以便随时可以因应空间的条件,再作打算。
    因此在程序规划时,对空间的安排,应该优先考虑使用频率。也就是说,要设法将
使
三、程序流程
    程序有一定的运行规律,称为「流程」,意即在执行时,依照预先安排的顺序,一
一流经的过程。
    传统的程序写作法,流程非常重要,因为人需要根据一种理念,以逐步检验并付诸
实现。但自从模块受到重视后,每个模块代表一种完整的功能,而功能的集合所能实现
的效果,远非流程可以表达。这一来,流程的重要性减低了,其地位降到只属于结构中
的一部份而已。
    因为模块是可组合的,模块越多,主流程便越短。虽然每一个模块也都各有其流程,
结构良好的模块,又可再细分为若干子模块,以此类推。因此,流程远不如模块灵活,
观念上也显得呆板。
    不过,即使在模块设计过程中,有时也有必要借着流程逐步推理,以了解细部的结
构。在这种立场,流程的应用原无可厚非。可是一旦反客为主,程序员不用流程即无从
思考,就大谬不然了。
    流程属于单线思考,人虽然经常使用这种流程推理,但更重要的能力却来自「抽象
思考」。抽象思考是指人在许多错综复杂、相互纠结的现象中,能立即掌握重点,针对
目的,解决问题。
    在程序上,这种抽象思考相当于对所有模块的全面认知,而非仅仅是流程的推理。
有了全面的认知,灵活地加以调用,程序的功能就更上层楼,大大的提高了。
    如果程序员只知道根据流程写程序,习惯养成后,不仅程序笨拙不堪,连人的思考
方式都连带受到影响。一般所谓的「匠气」、「呆滞」,就是这种机械式训练的结果。
    因此,我不赞成利用流程来规划程序,但在解释或说明某种过程时,并不排除流程
的方便性。
四、流程图
    流程的第一步是画流程图,根据流程图再作细部流程,然后根据细部流程去了解或
编写程序。
    以上面例子,先制作流程图如下:
        ┌─────┐
 ┌>───┤表格码输入│
 │    └──┬──┘
 │    ┌──┴──┐
 │    │取 一  码 │
 │    └──┬──┘
 │┌──────┴──────┐
 ││根 据 各 码 的 条 件 作 图│
 │└──────┬──────┘
 └───────┘
    请注意上图并没有出口,这是模块的特色之一,当码=0时,就进入结束程序。本
子模块的工作,便是要安排好数据,再回到来处。
    上面说过,每个码是根据组码定义而来,每次取一码后,立即根据码的预设条件作
图。(见第一节一、任务)这样不仅速度快,空间也精简。
    当然各码都有其子流程图,由于太简单,几句话便交待完毕,不必再作图了:首先
确定位置、宽度、长度,即可画直线或横线,如此而已。
五、细部流程
    细部流程最重要的,是要确定寄存器的功能,另外需要缓冲器辅助的,也应在此详
细说明。至于要详细到什么程度,则须根据程序的复杂性及写作的程序员而定。
    如果写作流程及程序为同一人,且无留供他人参考的必要时,细部流程甚至可以免
掉。但若是集体制作,而且需要保留档案,则不仅有必要,更须写得明确,让他人能够
一目了然,不论任何人都能接手才是。
    由于前面所举的例子太简单,如果要写细部流程,不待写完,程序早写好了。所以,
有时也不必过分拘泥形式。在下节指令应用中,仅以附注的方式说明细部流程,与程序
相对照,反而更有效率。
六、工作进度
    工作进度最重要的意义,不在于增加制作的速度,而是培养一种敬业的精神以及对
工作的判断能力。
    工作进度的掌握靠进度表,而制作进度表需要对全部的工作有相当的认识。所以,
进度相当于全面地、有系统地思考工作的细节,对程序员的工作能力的提高有极大的帮
助。
    当然,进度能有效地督促工作,每当进度如期完成,对程序员而言,即是一种成就
感。在制作大型程序时,时间往往拖得很久,如果没有进度作参考,人往往会有一种迷
失在汪洋,不知身在何处的失落感。
    能力强的人,经常能正确判断工作所需的时间;反之,不知道工作需要多久,或者
所预定的进度与事实相差太远,都表示着程序员的能力有限或不足。
    不过,写作程序完全要符合进度,也是不正确的观念。前文讨论过,写程序是种艺
术,而非流水作业式的生产,创造性强的艺术工作是不可能用进度来加以控制的。
    进度的制作方式没有定则,只要记下工作项目,预计完成时间,实际完成时间即可。
只是制作是一回事,执行又是另一回事,唯有认真负责的执行,才会有实用的价值。
    执行的方式不外每天或定期查阅进度,如果发现进度不符合,应该立刻分析原因,
并做修正调整。至于所分析的结果,最好能记载下来,以作下次改进的参考。
    如此这般养成了习惯,自然而然,就有了自动分析判断的能力,而且还会增进规划
和设计的理念。

上一页    下一页