汇编语言的艺术之二:准备工作

来源:互联网  作者:本站整理
摘要:汇编语言的艺术:(组合语言的艺术)准备工作第一节 系统一、系统之选择只因真正瞭解电脑的人太少,迷信名气的结果,使得 IBM PC/AT占有了市场。为求电脑普及应用,我们唯有因陋就简,针对 IBM PC/AT及其兼容系统,作进一步的分析和说明……

第二节  应用工具的制作

一、联接目标档(OBJ Files)

程式完成以后,相互间的联结,越大越难,有时是结构的改变,有时是档名的变动。不论什么因素,在在都需要加以维护,而且对工作效率关系重大。

因此,需先建立一个 do.bat 的执行档,其内容为:

1:LINK/M @XXXX

此 XXXX 为一记录档,其中记载所有需联结的目标档名,如果有任何异动,直接更改此档即可。

在联结时,执行 DO 即可。

例如:要制作 draw.exe 档,已有 dr1.obj .. drn.obj 以及dr-seg.obj 等档,则此 xxxx 档内容应为:

1: DR-SEG+
  2: dr1+dr2+.. drn
  3: DRAW,DRAW,,

在执行 do 后,如果没有错误,所产生的 draw.exe 以及draw.sym 即可供测试。

也可在第三条后加入:

4: symdeb (或仅用 s)draw.exe draw.sym

似此,在发展初期,立即可以测试。如果不需再次联结,将第四条另外作一 .bat 档,随时执行亦可。

另外有一点需要注意的是,为了要让可执行的程式由指定的起点开始,应在原始档 .asm 的结束格式标记‘end ’后,加一起点的标题名称。

此标记不论有多少,联接目标档时,会以第一个找到的标题为唯一的入口。如果程式很多,参与工作的程式师也多,在分开测试时,经常使用自己的入口,一旦联接在一起,就可能发生错误。

解决的方法是由负责联接的程式师,事先准备好前述XXXX记录档,将带有入口标记的程式放在最前面即可。当然,将其他程式标记后的标题删除亦可,但不如前法效率高。

二、目标档侦错及工具

在使用 debug时,因为名称简短,用法也简单。若使用「标题侦错」symdeb.exe则不然,因为首先要生成.map档,测试时,输入文字也较多。对不断使用的人来说,难免嫌烦。简化的方法,是先制作执行档:s.bat 及 sm.bat

s.bat 是专供指定程式侦错用,内容为:

1:symdeb %1.sym %1.exe
  这是指已经有了原档的 .map 时,如果程式刚联接完毕,且在联接档中,没有生成 .map 的语句,则应制作 sm.bat 如下:

1:mapsym %1.map
  使用「标题侦错」工具有很多优点,其功能较 DEBUG强得多。但是使用者必须注意,需要测试的标题,应该在程式中宣告PUBLIC,否则无法直接跳到该处。
  尚有些特殊效果的程式,也应备妥测试的工具,甚至以利用「监视器」的方式,用另外一台电脑来控制。有一些通讯软件,如 xtalk加上symdeb.exe,通过串行埠(serial port )可以联机调试,其手续如次:

1,先在待调程式的主机上输入通讯指令:
  C:\>MODE COM1:9600,N,8,1
  c:\>symdeb myfile.exe

2,再于已与主机经串行埠联接的副机上输入:
  C:\>XTALK
  进入指令输入状态,再输入:
  C:\>SP
  表示设定传输速度,一般多采用9600,但视主机而定。
  C:\>9600
  最后,输入操作指令:
  C:\>GO LO
  表示用区域网络,即串行埠口。
  这时等待联机成功的讯号,见到萤幕上出现“-”,即可  开始侦错。

3,在主机方面,尚要输入:
  C:\>=COM1 ( 或COM2,端视双方的通讯口而定 )

4,至于侦错方式,与利用一台电脑时相同,只是此时在主机上出现的是执行后的结果,而由副机控制侦错步骤。

第三节  分类定义

一、段名(Segment Name)定义

对段名多于一个的程式,最好先有一个定义段的程式,以DRAW为例,假定程式为两段,一为控制程式段,一为绘图程式段。资料分为三段,一为应用资料,一为参考资料,以及制作资料。此外还有一资料索引段,合计有六个段。

兹建议,在通用的基础上,简化段名,将段分类如下:
  程式段 (CODE SEGMENT) 定名为 CG
  资料段 (DATA SEGMENT) 定名为 DG
  索引段 (INDEX SEGMENT)定名为 IG
  记忆段 (MEMORY SEGMENT) 名为 MG
  特设段 (EXTRA SEGMENT)定名为 EG
  堆栈段 (STACK SEGMENT)定名为 SG

当各段超过一组时,则再加数字以区分之。
  如在 dr-seg.asm 中,可设为:
  1: TITLE   SEGMENT DEFINITION OF PROGRAM ‘DRAW’
  2: CG1   SEGMENT PUBLIC
  3: CG1   ENDS
  4: CG2   SEGMENT PUBLIC
  5: CG2   ENDS
  6: DG1   SEGMENT PUBLIC
  7: DG1   ENDS
  8: DG2   SEGMENT PUBLIC
  9: DG2   ENDS
   10: DG3   SEGMENT PUBLIC
   11: DG3   ENDS  
   12: IG    SEGMENT PUBLIC
   13: IG    ENDS
   14:       END

在 SEGMENT PUBLIC 之后,有多种表示方式:

SEGMENT PUBLIC XXXX

XXXX=CODE 表示为程式段,在联接时,属程式的段与段前后衔接。两段程式之间,以 000H 填充至「节」( 每十六个字元为一「节」 )之首位。 
      XXXX=DATA 表示资料段,在联接时同上。 
      如果程式师为了某种原因,必须严格控制程式之位置及长度时,不宜使用上述两种方式。 
      最简单之陈述方式,即在 SEGMENT PUBLIC之后,保持空白。 
      XXXX=BYTE 表示程式联接后,各程式之间紧密接合,不留空位。这种方法,有利于程式精简。 
      XXXX=WORD 表示程式联接后,各程式之间紧密接合,但在后面的程式必然由双数位起。

又如在 XXXX 前后加以引号如:SEGMENT PUBLIC 'XXXX'

此一宣告,用以通知汇编程式各段的顺序及定义。因此在编写程式时,只要使用的段名及定义与本档相符,不管将各段安排在程式任一位置,都不致发生错误。

‘XXXX’与本段程式的排列顺序有关,在联接时,先将引号中的字串排序妥当,各程式即依此顺序排列之。

也就是说,凡是使用了引号,则程式联接的顺序,即以在引号中字串,于联接时出现先后为顺序。

单一程式档的错误不难测知,但若各段之间发生错误,对经验不足的程式师,将有无从下手之虞,不得不慎!

一般说来,在联接时,最令人头痛的错误讯息为:
  'fixup overflow at nnnn..'

不论其错误提示内容如何,此种错误的发生,多半是因为段与段之间的标题、缓冲器或是暂存器的使用发生了混淆,联接程式得不到正确的信息所致。

解决方法是在第一个错误讯息出现时,立刻以‘Ctrl_C’停止汇编,记下第一个讯息,再在原程式中,找到该位置,(多半为一标题位置)在此标题之前,一定会发现与「段」有关的错误。

二、原始档(Source File)档名定义

在共同设计大型模组时,程式师间的默契,全赖事先相互约定。否则程式越大,所面临的困难将越多,经常耗时费事,甚至最后功败垂成。

因此,在设计之初,必须妥善规划,将一应有关的档案、名称、功能等,皆明确地加以定义。参与设计的程式师,更必须严格遵守,方能得心应手。

原始档名的定义,其目的有三:

1,代表程式设计者:当制作的程式甚多时,一见档名,就应能分辨出各个程式的设计人。再如某程式师所编程式在一  个以上,则应在其本人代码之后,加一数字编号。这样,遇有任何问题,立即可以找到来处,进行追踪。

2,代表程式功能:每当联结后发生问题时,应能由档名查知问题所在,故每种功能宜给予适当的名称。

3,代表联结的关系:除了功能外,有时尚须表示各程式之间的联结关系。如某一程式必须安排在另一程式之前或后,亦应在档名最后,以数字表示顺序。

若参与的程式师不超过廿人,则以一字元为限,各人事先选定一个字母,作为档案名称的第一字元。第二字元则视该程式师是否编写一个以上的程式而定,是则取一数字代表之,若无则免。
  功能以三到六字元为宜,能统一长度将更为方便,余下一字元留供数序用。
  例:程式师代号为‘C’,本程式之编号为3,功能为‘DRAWS’,此外并无联结关系,则其名应为:
      cdraws3.asm

三、标题定义

程式在整理或测试时,最大的困扰,是寻找某一个标题的出处或功能。如果在同一档中,尚可利用cref.exe,列印出一份对照表来;如果不知道出自哪一个档案,在众多的程式中,就只有望洋兴叹了。

至于功能,如名称定得太长,不仅输入、修改不便,而且会使得程式看来杂乱无章,令人眼花撩乱。如果定得太简单,或各人任意定名,则难以理解。

所以,标题定名之重要性,不下于程式之写作。尤其是在参与人数众多时,标题不仅要统一,而且要能代表所有必备的讯息。

标题所代表的讯息有:
        A x x x x x x x x
        │└┬┘└┬┘└── 分支代号
        │  │  └──── 延伸定义
        │  └─────── 功能名称
        └───────── 程式出处

1,程式出处:如果很多人同时参加一个计划,而某程式师仅写了一个程式,此定义即为该程式师之代码。否则尚要附  加编号,以便随时可查到。即使只有一个人写作程式,程式可能不断扩大,为了制作的方便,或为了模组的分割,常有必要将程式分到其他档中。因此,一段程式究竟出自于哪一个档案,全赖标题表明,以便能迅速地找到。 
      程式出处一般用一个字母即可,如前述第一个字母A代表此段程式来自编号为A的原始档;或属于以A为代号程式师的程式。

2,功能名称:除若干已知会用到的功能可以事先定义外,其余的多半是在发展过程中,针对需要而产生。对功能定义千万不要掉以轻心,一个程式的再利用价值,常与其功能定义息息相关,明确的定义,可以令人对其功能及应用方式一目瞭然。
      功能名称长度以三个字母为宜,太长则输入费时,尤其是国人不见得个个英文了得,与其写错,不如藏拙。
      如:DSP 表示萤幕显示功能
          PRN 表示列印功能
          KIN 表示键盘输入功能

3,延伸定义:若功能相同的程式过多,2,中的定义方式难以分辨,则可再加一延伸定义。
      如:DSPDOT表示显示点阵
          PRNCHI表示列印中文
          KINASC表示输入 ASCII 字符

4,分支代号:在程式中常有分支,分支代号最理想是由小而大,依序安排。但由于写作时常难以预知后情,故宜先留空号,以便扩充。
      如:DSPDOT10
          PRNCHI06
          KINASC24

四、缓冲器定义

B x x x x x x x 
        ││└┬┘└┬┘
        ││  │  └─── 延伸定义
        ││  └────── 功能名称
        │└──────── 类型
        └───────── 缓冲器保留字

第一个字母规定用‘B’,为缓冲器保留字。
      第二个字母定义其类型:
      Q=QWORD   如:BQxxxx 缓冲器长度为8字元。
      D=DWORD   如:BDxxxx 长度为4字元。
      W=WORD    如:BWxxxx 长度为2字元。
      B=BYTE    如:BBxxxx 长度为1字元。
      S=STRING  如:BSxxxx 不限长度,但限BYTE型。
      O=ORIGINAL  如:BOxxxx 表不可破坏的原始资料。
      F=FLAG    如:BFxxxx 用作旗号。
      第二字母以后所采用功能或延伸定义,与三、2,3相同。此外,所有缓冲器皆应统一设在缓冲器专用程式中,若系临时使用,或尚未正式联接,亦应设在各程式之首,以便于查阅、修改。

【相关文章】好搜一下
perl语言详解

perl语言详解

Perl最初的设计者为拉里·沃尔(LarryWall),它于1987年12月18…