奇趣技术网 收藏本站
设为主页
商务合作
首页 新闻中心 行业动态 软件新闻 安全资讯 病毒预警 漏洞发布 操作系统 Dos Win9x Win2000 WinXP Win2003 WinVista Linux Unix
数据库 DB2 Access MSSQL MySQL Oracle Sybase 编程技术 ASP PHP JSP CGI/Perl XML .Net C/C++/C# VB VC Delphi Java 汇编
安全技术 安全教学 工具介绍 漏洞利用 病毒防范 入侵检测 防火墙 安全防范 汉化破解 攻击实例 加密解密 技术论坛
中华网络安全联盟 >> 程序开发 >> 汇编 >> 汇编语言的艺术(组合语言的艺术)--准备工作
程序开发
Asp
PHP
JSP
CGI/Perl
XML
.Net
C/C++/C#
Visual Basic
Visual C++
Delphi
Java
汇编语言
  • JDBC专题介绍(1)

  • 全面解析JDBC(9)

  • 全面解析JDBC(6)

  • 全面解析JDBC(5)

  • 全面解析JDBC(4)

  • 全面解析JDBC(1)

  • MySQL中修改密码及访问

  • SQL语法参考

  • 汇编语言的艺术(组合语言的艺术)--准备工作
    字体:

    中华网络安全联盟    作者:佚名    来源:网络转载    时间:2006-3-21

    汇编语言的艺术(组合语言的艺术)--准备工作:    第一节  系统

    一、系统之选择

        只因真正瞭解电脑的人太少,迷信名气的结果,使得 IBM PC/AT占有了市场。为求电脑普及应用,我们唯有因陋就简,针对 IBM PC/AT及其兼容系统,作进一步的分析和说明。
        尽管使用 80486 CPU的微电脑已问世,我个人认为以其造价及功能而言,并不符合效率法则。在从事艺术工作的立场,价值的高低,与所采用的材料没有绝对的关系。更何况我们正要证明,利用组合语言的制作技巧,能够使功能不高的微电脑发挥最大的边际效益。故本书仅以8088 CPU指令为研讨对象,至于程式应用在什么机型,就不在本书的考虑范围内了。

    二、目录及磁盘

        假定读者为有经验的程式师,且电脑为 IBM PC/XT/AT。 则在着手制作程式之初,应该先将系统准备妥当。即所谓「工欲善其事,必先利其器」,如果未能注意到下面所提的细节,仅仅制作一、两个程式尚可应付。待工作量一大,程式渐渐增多,不是某些程式找不到,就是找到了也不能一目瞭然。结果是心烦意躁,马马虎虎,另外再写一个,勉强应付了事。
        硬盘空间较大,应行注意的事相对的也较多。首先应妥善规划好目录及子目录的分类及应用方式,否则每当要找一个档案时,往往有大海捞针之叹。再不然,在修改程式时,如果将不同的版本放在一起,一定会张冠李戴,错误百出。
        每位程式师都应该有自己的目录,而且每个不同的整套档案都应有不同的子目录,这样方能明确的分辨以及应用。而最有效率的方法是,在每一子目录中,档案数不宜太多,且仅存放在同一工作项目下所需要的程式。
        一旦硬盘坏了,所有贮存资料均将付诸流水。为了安全,一定要用软盘备份。最好每天复制一次,虽然每次复制,相当麻烦,但是万一程式被毁坏,那种损失是无从估计的。
        最好的方法,是制作一个专门复制的工具,一般用 .bat 应用程式,每天工作完毕,只要执行一次即可。

    三、应用工具

        程式写作是为了控制电脑运作,应用工具则是将程式师的观念和理解转化为能够连续执行的指令。因此,市面上的应用工具虽多,却不见得对程式的写作有所助益。下面列了几种,只要运用纯熟,绝对够用了。

        程式写作:EDLIN ,PE II,WS等。

        程式编译:masm.exe
                  早期 (1.25) 版本容许较多的「外界标题」,即external label,但该版本仅限用于8088指令,较宜大型程式处理。
                  4.0 以前的版本,于档案开始时,可用.xcref以产生标题及缓冲器的位址对照表。但后期的版本会发生错误,不能再用。

        程式联接:link.exe 
                  早期的版本对 segment    public 'xxxx' 有些规定,但 3.0以后,除了对code及 data 有效外,其他如 byte 及 word 等皆无作用。

        程式侦错:debug.exe 或 symdeb.exe 及 mapsym.exe
                  后两者为套件,必须另购。其优点为在侦错过程中,可以使用原程式中的标题名称,且可设「断点」等,侦错方便,功能较强。

        系统处理:pctools.exe 是 dos下很有用的工具,可以作档案管理,也可用来直接修改程式机器码。此外,连机时可以用ll.exe 或xtalk.exe等。尤其是系统程式的侦错,经常需要用联机的方式,以另一台微电脑作为监视器。

        这些工具应统一放在 \dos 子目录中,且须在系统之自动执行程式(autoexec.bat)里,先设妥优先通道(path)如:

        1:PATH=\DOS;
        是则,不论在哪一个子目录中,前述之工具皆可使用。

    四、简化名称

        前述各种工具,在程式侦错过程中使用频繁,为了应用上的方便,如果能少输入一些字符,不仅节省时间,且可避免错误。令用者在惯性反应下,得以集中精神,思考其他细节。
        简化名称是最简单的方法,最好只用一个字母,由于长度相等,其后面的档案名称,就可以利用系统所提供的“F3”「复制上行」功能,不必再行输入。

        是以:edlin.com 改为 e.com
              masm.exe  改为 m.exe
              link.exe  改为 l.exe
              debug.exe 改为 d.exe
              symdeb.exe 改为 s.exe
        例如:在完成一个程式后,若要汇编,只要改第一个字母即可。
              c:\>e myfile.asm ( 原来在系统中输入的字符 )
        此时仅输入“M”,再按“F3”键,立即变为:
              c:\>m myfile.asm
        此外,如不需 .lst 等档案,则再加一“;”即可。
              c:\>m myfile.asm;
        “L”及“D”等同样都可依循上面的方法,看来是雕虫小技,但实际上所节省的时间及精力却不同凡响。

    五、参考资料

        除专门性的资料外,程式师应该备妥各种有关输出、入,各种周边设备的参考资料或手册等,以便随手查阅。
        最重要的是软件参考手册 MS-DOS Software Reference,其中有各种中断命令的使用规格。唯应注意的,是有一些中断功能与IBM BIOS相同,我建议读者不要使用这些中断,因其调用过程中,要借道BIOS,会使速度减慢。
        其次为 IBM Programmer's Manual 的BIOS中断规格, 是处理所有周边设备必需的工具。
        正因为它涉及周边设备,在设计中文系统时,输出入、显示及列印等功能都有待修改,这本手册更须彻底瞭解。
        此外还有键盘的输入码表,也是编程必备的资料,本书附录三即为简要的码表介绍。
        如果是编写应用程式,上述的资料已足够应付,但若涉及系统,则尚需瞭解系统的记忆空间安排,下表为 IBM微电脑的记忆区结构。各种厂牌设计理念虽有差别,但大同小异。
        系统段  位  址              机  能  用  途
                         ┌──────────────┐
        0000  0000H      │中断调用表                  │
                         ├──────────────┤
        0000  0500H      │DOS 及系统操作区            │
                         ├──────────────┤
        0000  4C00H      │周边控制程式                │
                         ├──────────────┤
        0000  5400H      │COMMAND 运用                │
                         ├──────────────┤
        0000 0E0A0H      │使用者操作空间              │
                         ├──────────────┤
        000A  0000H      │萤幕缓冲区(VGA)             │
                         ├──────────────┤
        000B  0000H      │萤幕缓冲区(CGA,EGA)         │
                         ├──────────────┤
        000C  0000H      │EMS 记忆体扩充区            │
                         ├──────────────┤
        000F  0000H      │ROM BIOS  程式区            │
                         └──────────────┘
        上述之系统段,调入段暂存器中时,原来的 000AH应该是0A00H,余同。
        又使用者操作空间的起始点,因各家设计而异。
        第二节  应用工具的制作

    一、联接目标档(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相同。此外,所有缓冲器皆应统一设在缓冲器专用程式中,若系临时使用,或尚未正式联接,亦应设在各程式之首,以便于查阅、修改。

        第四节  统一格式

    一、格式统一之优点

        不论采用何种程式语言,凡是共同工作、须相互研讨,或者在同一部门中,分担成败责任者,应该有统一的程式写作方式。这样不仅便于沟通,提高程式的品质,且可避免因某一程式师之离职或出缺所造成的后遗症。
        良好的程式,应如一篇美妙的文学作品,其中有技巧,有意境。其功能不仅表现在执行的效率上,也可以作为同行间学习、欣赏的媒介,这些都必须透过统一的格式达成。
        尤其是把组合程式写作当作一种艺术创作,就必须经常相互观摩,如果没有共通的格式规定,则这样的程式和「天书」可以说没有多大的分别。不论注释写得再好,一般程式师自己都怕看自己的程式,更何况参阅他人的? 但若有统一的格式,养成习惯后,不仅易看易懂,而且寻找、修改方便,写作也轻松省事。

    二、规格

      1,统一用大写字母,以利于阅读。
      2,空格处应采用 TAB,齐头等距,一目瞭然。
      3,标题之后立即改行输入,以便阅读。
      4,每行不得超过70个字母,以免长度不等,画面紊乱。
      5,注记位于指令后,在第五个 TAB的起点,空间不足时,可换行,但位置齐一。
      6,所有缓冲器统一定义在程式之前,不可夹杂在程式中间。
      7,除了需要作超过程式段的FAR CALL使用‘PROC FAR’外,切勿使用‘PROC NEAR ’形式,因这种写法毫无意义。 
      8,程式开始时,应有注记说明使用要点。

        以下举例说明统一格式:
        1: PAGE  60,132
        2: TITLE [程式名],[程式师代号],[编号],[功能说明]
        3: 
        4: DG       SEGMENT PUBLIC 
        5:          extrn   bwsca1:word,..
        6: DG       ENDS
        7:
        8: ..
        9: ..
       10: ..
       11:
       12: CG       SEGMENT PUBLIC 
       13:          extrn   mmmm:near,..
       14:          ..
       15:          public  xxxx,yyyy,..
       16:          ASSUME  CS:CG,DS:DG,ES:DG
       17: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       18: ;   REM …………                       ;
       19: ;       ………………….             ;
       20: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       21: START:
       22:          CLD
       23:          MOV     AX,DG
       24:          MOV     DS,AX
       25:          ..
       26:          ..
       27:          ..
       28:
       29:CG        ENDS
       30:            END     START

        第一条的 PAGE 是供列印用的「保留指令」,表示每页所印的行数及列数。其后之 60,132 即为60行, 132个字符。
        第二条的 TITLE  为供查阅之「保留指令」。
        前述REM 注记栏中,应说明该段程式的功能、应用条件,以便其他程式师共同使用。

    三、注记

        注记的目的在于日后自己或他人能很容易地做程式修改、维护。因此所做描述当力求详尽。不幸的是,不论多么精彩的文句,总有不足之处。因此,注记时需把握重点,大体说来,程式需加以说明的,不外:

      1,功能:做什么工作,需要何种先决条件。
      2,参数:设些什么数据,以供本段程式处理。
      3,缓冲器:用什么缓冲器,其工作特性如何。
      4,结果:执行后所产生的结果。
      5,子程式调用:在本段程式中,所需调用的子程式名。
      6,重要声明:如暂存器是否被破坏,或其他注意的事项。
        如:
        【功能】:读键盘缓冲区输入码,依性质返回ASCII+扫
                  瞄码或中文内码
        【参数】: AH = 00H
        【返回】: 11AL< 80H,AH = 扫瞄码,AL = ASCII
                  12AL≧80H,AL = 四字元中文内码之一
        【破坏暂存器】:AX
        【备注】:以本功能取中文内码,须连取4次,依序得
                  到一中文4字元内码。
        当然,如果时间充足,最好能有程式的全部说明,以及制作、修改的细部记录。
        问题在于任何程式发展之初,一定乏善可陈。再加上不断的修改、增补,其间变化复杂无比。程式师又要全神贯注,解决问题,又要考虑如何注记,一心两用,必然谈不到效率。
        那么怎样做才对呢?我建议先让程式师自由发挥,在初期有无注记无关紧要。待程式完成了,大致上没有错误,这时,就应该停下来,从头到尾,将程式彻底整理一番。 
        这样不仅加注记容易,而且程式师有机会重新「欣赏」自己的心血结晶,该改的改,该合并的合并,该删的删。最后,程式师经过反思,研究,技术将会大幅度进步,程式更精简,注记也正确无误,工作也达到最高效率。
    字体:
     
    设为主页 收藏本站 联系我们 友情连接 商务合作 网友留言
    Copyright©2006-2008 中华网络安全联盟 All rights reserved.