第12卷 第1~2期 潍坊教育学院学报 V o l.12N o.1~2 1999年 第1~2期 JOU RNAL O F W E IFAN G EDU CA T I ONAL COLL EGE Jun.1999 如何顺利编写汇编语言程序孙义欣1 张华彬2(1潍坊教育学院计算机教研室;2潍坊教育学院教务处,山东青州262500)[摘要] “汇编语言程序设计”是计算机专业的一门较难的课程,但它也是微机原理、操作系统、接口技术等课程的先修课程。
为帮助汇编语言初学者顺利学会编写汇编语言程序,本文从汇编语言程序的上机过程和汇编语言源程序的格式两个方面作了较为详细的说明。
[关键词] 段寄存器 程序段前缀 PSP 汇编 转换“汇编语言程序设计”是高等院校计算机硬件、软件及应用专业学生必修的核心课程之一。
它不仅是计算机原理、操作系统等其它核心课程的必要先修课,而且由于汇编语言兼有机器语言和高级语言的一些主要优点,在软件开发中十分有用。
对于从事计算机软件开发的人员来说,掌握汇编语言程序设计,无疑将使其进入更高层的程序设计境界。
而要利用汇编语言顺利编程,不仅对机器硬件的一些特性要有一定的了解,还要熟悉汇编语言程序的上机步骤和汇编语言程序的基本结构。
汇编语言的指令相对于高级语言中的语句来说比较难理解,因此,很多初学者对汇编语言编程都感到不易掌握。
为此,笔者从汇编语言的上机过程和汇编语言程序的基本结构两个相对固定方面做了较为详细的说明,以帮助汇编语言的初学者顺利编写汇编语言程序。
一、汇编语言程序的上机步骤学习汇编语言编程应了解汇编语言程序的上机步骤,下面以M A S M宏汇编程序的处理过程为例,说明汇编语言程序的上机过程。
1.用编辑软件建立汇编语言源程序。
可利用各自机器上所装的编辑软件来进行,应该注意的是,编程者应该知道自己所建立的汇编语言源程序是.COM格式还是.EXE格式的,两种格式的源程序是不同的(见后述)。
建立的汇编语言源程序应为文本文件,存盘时应规定文件扩展名为.A S M,假设我们建立的汇编语言源程序名为ex.as m。
2.用汇编程序把源程序汇编成目标程序。
源程序建立好以后,应用相应的汇编程序(如M A S M)将源程序汇编成扩展名为.ob j的目标文件。
如:C>m as m ex(注:文件名不用.as m扩展名)。
若在汇编时检查出源程序中有错误,应返回第一步修改源程序后,再进行汇编。
3.用连接程序将目标文件连接成.EXE文件。
经过汇编程序处理而产生的目标文件已经是二进制的文件了,但它还不能直接上机运行,还需由连接程序对其进行连接,以便把目标模块中的浮动地址进行重新定位,以及把本模块与其它程序模块连接起来形成一个装入模块。
连接的程序为:C>L ink ex(注:目标文件不用.ob j扩展名)。
连接完成后,若有错误信息,则应返回第一步继续检查和修改源程序,再进行汇编和连接。
若没有错误提示,则表示连接成功。
4.用转换程序将.EXE文件转换为.COM文件。
若所编源程序为.COM格式的文件,在连接成功后,还必须将其转换成扩展名为.COM的文件才行。
转换的方法为:C>exe2b in ex ex. com(注:ex为连接程序所生成的扩展名为.EXE的文件名,不用扩展名;为转换后所产生的扩展名为.com的文件名,必须要加.com扩展名,否则将生成扩展名为.B I N的另一种二进制文件)。
5.在DO S提示符下打入文件名运行。
上述步骤完成后,即可在DO S系统提示符下打入文件名运行程序,以验证程序的正确性,若运行情况与我们所要求相同,则该程序上机完成。
二、汇编语言程序的基本结构要顺利地编写汇编语言程序,应真正认识和了解汇编语言程序的结构。
为此,需弄清程序段前缀的有关内容和作用以及.COM格式文件和.EXE格式文件的区别。
1.程序段前缀(PSP)的有关说明。
当我们从DO S提示符下键入一个外部命令时,DO S并不是直接将程序体加载到内存中,而是确定当时内存最低的可用地址作为程序的装入起始点。
先开辟一个100H字节长的区域,然后才加载真正的程序体。
由于这块区域占据了分配给加载程序的内存空间且位于实际程序体的前端,故被称为程序段前缀(PSP)。
程序段前缀作为DO S与被加载程序的接口,其中包含许多重要的数据信息(参看有关手册)。
而在PSP+0字段中存放着一条DO S程序结束的指令(中断指令I N T 20H),在PSP之后的位移0100H 处(对.COM格式文件来说)或某处(对.EXE格式文件来说)装入实际的程序体并把控制权转交给它。
如果被调入的程序段在执行完后能安全地返回PSP+0字段,则由中断I N T 20H 指令将控制权传回给DO S的命令处理程序COMM ,程序才能安全结束。
因此,在编写程序时应注意保存PSP所在的段地址和偏移量0。
格式文件和.EXE格式文件的区别。
如上所述,DO S在装入用户程序时,在程序段位移量为0地址处建立PSP,并把用户程序装入其后的内存单元中。
程序开始运行时,某些寄存器将指向PSP。
扩展名为.COM和.EXE的文件,都是在DO S命令行上可以直接运行的文件,但它们各自所建立的PSP是不同的,或者说它们与PSP的关系是不同的。
正因为如此,在编写程序时,就应按照各自PSP的有关规定编写。
当DO S加载的是外部命令.com程序时,在该程序执行以前:①所有的段寄存器(CS,D S,ES,SS)都指向PSP的段地址,即由命令处理程序COM2M 分配的程序段首地址。
也就是说,在.COM文件中是不分段的。
②指令指针指示器IP被置为‘100h’。
由于计算机中执行的指令都是由CS∶IP所指示的内存单元之中取出的,因此,在.COM格式的程序中,第一条可执行的指令必须放在偏移地址100H处。
③SP 寄存器指向64KB的末尾,即(SP)=FFFEH,并置栈顶值为0。
而当D O S加载的是扩展名为. EXE的可执行文件时,程序的定位和段寄存器的设置就复杂一些。
一个.EXE程序含有由连接程序建立的程序重定位表,装入程序可以根据这个表确定程序的某些部分的定位地址。
因此,CS,IP,SS和SP被设置为由连接程序所定位的值。
由于.E XE文件允许分段,因此程序运行后,D S和ES段寄存器可以指向用户程序中定义的数据段和附加段。
但是,当用户程序开始运行时,D S和ES总是指向程序的开始地址,即PSP的段地址。
只有把相应段地址实际传送给它们后,才指向用户程序定义的数据段和附加段。
在汇编语言指令中,中断指令I N T 20H具有“程序结束”的功能。
我们在编写汇编语言程序时,若在程序结束时使用中断指令I N T 20H,就能安全地返回到命令处理程序COMM 。
但是应当注意,在调用这个功能之前,必须保证程序结束时代码段寄存器CS应包含程序段前缀PSP的段地址。
如果我们编写的程序为.COM格式的文件,那么在程序中,不需要做特殊处理,因为CS自始至终都是指向PSP的段地址。
因此,可以用I N T 20H指令结束程序;而编写的如果是.EXE格式的文件,如前所述,代码段寄存器CS是指向由连接程序所定位的值,而不是PSP的段地址,因此不能用I N T 20H中断指令直接结束程序。
但是,在程序开始执行时,数据段寄存器D S是指向PSP的段地址,利用这一点,在此时,首先将D S的值(PSP的段地址)和0(PSP段的偏移量)入栈保护,然后才设置D S指向用户程序中定义的数据段,而在程序结束时,要安排一条R ET返回指令。
因用户程序为远过程,因此,利用R ET指令的功能将程序开始时保存在栈顶的0弹到指令指针指示器IP寄存器中,接着栈顶的D S值(原PSP的段地址)弹到代码段寄存器CS中,满足了程序结束时CS应包含PSP的段地址的要求。
至此,CS∶IP正好指向了PSP+0字段,恰恰在该字段内安排了一条中断指令I N T 20H,机器自动执行这条中断指令而使控制权返回到DO S。
格式文件和.EXE格式文件的框架程序。
根据以上所述,我们可以分别编写出. COM格式文件和.EXE格式文件的框架程序。
在编写汇编语言程序时,可以将此模式“套”在自己编制的程序上,并在其中填入实际内容即可。
(1).COM格式文件的框架程序:PRO GNAM SEG M EN TA SSUM E CS:COD E,D S:COD E,ES:COD E,SS: COD EM A I N PROC N EA R;将主程序定义为过程OR G100H;使其后的指令从偏移地址100h处开始STA R T:JM P BEG I N;程序的入口…… ;此处定义程序中用到的数据BEG I N;……;此处为程序中的具体内容call sub1…… ;此处也为程序中的具体内容I N T20H ;执行结束中断,程序结束M A I N END P;33333333333333sub1p roc near…… ;子程序有关内容retsub1endp;33333333333333PRO GNAM END SEND STA R T(2).EXE格式文件的框架程序:DA TA SEG M EN T … … ;此处定义数据段的内容DA TA END S;33333333333333EXTRA—SEGSEG M EN T… … ;此处定义附加段的内容EXTRA—SEG END S ;33333333333333STA CK—SEGSEG M EN T… … ;此处定义堆栈段的内容STA CK—SEG END S;33333333333333COD ESEG M EN T;定义代码段M A I N PROC FA R;把主程序建立为远过程A SSUM E CS:COD E,D S:DA TA,ES:EXTRA —SEG,SS:STA CK—SEGSTA R T: ;设置主程序的入口PU SH D S;将PSP的段地址入栈保存XOR A X,A XPU SH A X;将PSP的偏移值0入栈保存M OV A X,DA TAM OV D S,A X;将数据段的段地址送D S寄存器M OV A X,EXTRA—SEGM OV ES,A X;将附加段的段地址送ES寄存器…… ;此处为程序的实际内容R ET;执行返回指令,将保存的PSP的偏移值0和段地址分别弹回到IP和CS,执行I N T20H中断,返回DO S M A I N END P;33333333333333sub1p roc nenr… … ;子程序中的内容retsub1endp;33333333333333COD E END SEND STA R T 三、结束语以上仅从汇编语言程序的上机过程和两种汇编语言源程序的基本结构两个方面做了一些说明。