微型计算机原理与应用(王永山)第5章.ppt_第1页
微型计算机原理与应用(王永山)第5章.ppt_第2页
微型计算机原理与应用(王永山)第5章.ppt_第3页
微型计算机原理与应用(王永山)第5章.ppt_第4页
微型计算机原理与应用(王永山)第5章.ppt_第5页
已阅读5页,还剩142页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、5.1汇编语言程序的多模块连接5.2结构和记录5.3汇编语言程序和高级语言程序之间的连接,第5章多模块程序设计,返回主目录,第5章多模块程序设计,在第4章介绍的程序设计中,标识符(变量、标签、段名、过程名等。)所涉及的源程序都是在这个程序中定义的,这与这个程序之外的标识符无关。这个程序设计叫做本章将介绍多模块编程方法,也叫模块化编程方法。所谓的模块,从功能上讲,可以是整个大程序的独立部分,从结构上讲,它是一个以END结尾的完整程序。因此,一个源模块可以独立组装形成自己的目标模块。最后,连接程序将每个目标模块连接成一个可执行程序。模块化编程有以下优点:(1)一个复杂的程序可以分成几个模块,可以由

2、不同的人员分别完成;(2)各模块的任务清晰易懂;(3)单个模块易于编写和调试;(4)程序维护和修改方便;(5)现有模块可以直接使用。采用模块化编程时,需要合理划分模块,严格定义各模块的输入输出参数以及各模块之间的通信方式。当设计单个模块程序时,必须在该模块中定义模块中使用的各种标识符,如段、变量和标签,否则在组装过程中将给出错误消息。当设计一个多模块程序时,因为每个模块都是整个程序的一部分,所以不仅模块之间会有数据传输,而且模块之间还会有变量、标签和其他标识符的交叉引用。如何实现这种交叉引用,如何实现模块之间的连接,是汇编语言多模块编程中的一个重要问题,也是本章的主要内容。此外,多程序模块的连

3、接不仅适用于汇编语言程序模块,也适用于汇编语言程序模块与高级语言程序模块之间的连接。因此,本章还将介绍连接汇编语言和两种高级语言(BASIC和TURBO-C)的基本方法。5.1汇编语言程序的多模块连接,5.1.1多模块间的SEGMENT连接1。线段定义的完整表述为:线段名称、定位类型、组合类型、类别、线段名称、端点。段定义后,段名有五个属性:段地址、偏移地址、定位类型、组合类型和类别。前三个属性已在第4章中介绍过,本节将介绍最后两个属性,它们用于为连接过程提供多个模块之间的段连接信息。1)组合类型组合类型告诉汇编器向链接器提供关于该段落和其他段落之间的连接的相关信息,例如该段落和其他段落是否被

4、组合成同一段落;组合后,这个信息和其他信息有什么关系,等等。为了提供这样的信息,有六种不同类型的组合:NONE、PUBLIC、COMMONAL、at expression、STACK和MEMORY。定义段时,如果省略了组合类型,则暗示为NONE类型。(1) NONE类型:表示该部分与不同模块中的其他部分没有逻辑关系。连接后,每个模块中的每个段都有自己的段地址(也称为基址)。(2) PUBLIC类型:表示连接时,不同模块中相同名称和相同类别的段应该一个接一个地连接成一个段,其中所有变量或标签都有相同的段地址。连接顺序与用户在链接期间提供的模块顺序一致(连接的基本方法将在本节末尾给出)。每个模块中

5、属于公共类型的相同名称和相同类别的每个段的总长度不能超过64 KB。(3)堆栈类型:它被视为与PUBLIC类型相同,只是组合段被用作堆栈。当在段定义中指示堆栈类型时,这意味着堆栈段已经被确定。因此,在可执行文件被加载到内存中之后,该段的段地址已经在寄存器SS中,并且堆栈指针SP已经指向堆栈的底部。这样,我、(4)COMMONAL类型:表示连接时,不同模块中同名同类的段应连接成一个段,共享一个基址,相互覆盖。连接后,线段的长度取决于最长的公共线段的长度。(5) AT表达式类型:指示连接时,本段应安装在根据表达式计算的16位段地址上,表达式也可以是有效的常数。这种类型可以在固定的地址范围内设置我们

6、想要定义的段。必须注意的是,定义at类型的段不应包含任何带有初始值的指令语句或变量定义语句。但是,允许设置具有与标签或变量定义语句相同属性的标签或过程定义语句,而无需初始值。它仅用于将段指向存储区域中的某个段,以便段中的段名和变量与所指向的存储区域的段地址相关联。例如,如果您想使用过程名SUB1来表示BIOS中的某个子程序,我们可以定义一个段和一个过程如下:CODEBSEGMENTAT表达式1根Sub1 Procfar Sub1 Endp Code Bends,其中表达式1的值是子程序所在段的段地址,n是子程序在该段中的偏移地址。有了这个定义,当程序名SUB1在程序中被调用时,相应的子程序在基

7、本输入输出系统中被调用。还可以定义一个标签,并按组织指定标签的偏移地址,以便标签与段中的偏移地址相关联。(6) MEMORY类型:表示连接时,该部分应安装在所有其他连接部分(地址高端)之上。当有多个这种类型的段时,只有汇编程序遇到的第一个段被认为是MEMORY段,而其他段被认为是COMMON类型。图5.1显示了当不同模块的组合类型为公共和公共时的连接结果。在图中,两个模块的数据段是公共类型的。连接后,两个部分组合成一个相互覆盖的部分。第二个模块的长度是两个模块中间部分的长度。因为COMMONAL类型的段在组合后相互覆盖,所以该类型仅在不同模块采用公共缓冲时使用。在图5.1中,两个模块的代码段是

8、公共类型的。因此,在连接之后,两个模块的代码段也组合成一个段,但是它们没有被覆盖。相反,这两个代码段相邻地连接在一起,其顺序与LINK提供的目标模块的顺序相同。组合后部分的长度应该是两个代码段长度的总和。在图5.1中,两个源模块中的数据段和代码段都没有给出一个类别,这也是允许的。但是,如果在一个模块中给定了一个类别,而在另一个模块中没有给定类别,则两个模块中具有相同名称的段不能组合成一个段,并且它们不被认为是同一类的段。模块1和2如下:模块1:数据段公共dw20hdup(?)数据结束代码段公共代码结束,模块2:日期段公共dw 30h dup(?2)类别类别可以是任何合法名称,但必须用单引号括起

9、来。连接时,不同模块中相同类别的段将在物理上相邻连接在一起,其顺序也与LINK提供的模块顺序一致。当具有相同类别的段的段名不同时,它们在连接后处于相同的物理段中,但是它们仍然不属于相同的段,即它们的段基址不同。这样做的一个优点是容易巩固程序。编程时,它们都是独立的代码段,每个段都有自己的段基址,但连接后,它们在同一个物理段中,可以固化在一起。2。组伪指令伪指令格式:段组名,段名。格式中的段组名是用户定义的标识,其定义规则与语句名相同。格式中的段名是本模块中定义的段的段名。组指令提供了段的另一种组合。它将由segment语句定义的多个段合并到同一个段组中,该段组由段组名表示。同一网段组中的网段将

10、安装在同一物理网段中,并且它们具有同一段组中段的组合类型和类别可以不同。模块1:agroupgode 1,CODE2;段组组代码1段假设cs:组开始:代码1结束代码2段假设cs:组代码2结束结束开始,模块2:extrin var 1:字节,VAR2: WORD,var 5: word publicex 1,VAR3 DATASEGMENT VAR3DW?数据结束代码段公共代码ex1:代码结束结束,模块3:extrin var 4:字节公共var 5,EX2 DATASEGMENT VAR5DW?数据结束代码3段Ex2:数据结束代码3结束,2。模块间交叉访问的编程考虑伪指令PUBLIC和EXTR

11、N在不同模块间的相关变量和标签之间建立连接,从而使模块间的交叉访问成为可能。然而,当相同的变量(或标签)在不同的模块中被引用时,它们的基地址必须一致,这是设计多模块程序时应该考虑的主要问题,否则程序会运行不正确。在这里,基址的一致性有两层含义。首先,与每个变量(或标签)的偏移地址对应的段的基址应该一致;第二,当使用这些变量(或标签)时,段寄存器的内容必须是对应于变量(或标签)的段地址。我们首先解释第一个问题,即当变量(或标签)在不同模块中交叉引用时,对应于变量偏移地址的段基址是什么。一般来说,不同模块中的每个段(代码段或数据段)是否连接在同一段中。当一个变量的偏移地址在不同的模块中取用时,它的

12、段基址是相对于变量所在的段的段地址的。例如,在5.1.2中,有三个模块。组装和连接后,有两个代码段(代码和代码1)和三个数据段(数据1、数据2和数据3)。每个段中变量(或标签)的偏移地址与其段的段地址相关。例如,VAR1和VAR2的基址是DATA1的段地址,无论在模块1还是模块2中访问,它们都是相同的。然而,有时会有不同的情况。例如,当不同模块中的一些段在连接后不在同一段中,但是伪指令EXTRN被放置在某个段中时,它可能出现在不同的模块中以访问相同的变量,但是该变量的偏移地址不同。例如,在5.1.2中,如果伪指令extrnVAR3:字被放置在模块1的DATA1段中,当访问模块1和模块3中的VA

13、R3时,其偏移地址是不同的,因为模块1中VAR3的段基址是DATA1的段地址,而模块3中VAR3的段基址是DATA2的段地址。也就是说,在这种情况下,同一个变量(VAR3)的段基址在两个不同的模块中是不同的,所以它的偏移地址也是不同的,所以在访问这样的变量时应该特别注意。示例5 . 1 . 2 #;模块1:ext nvar 2:WOrd,SROUT:FAR ext nvar 3:WOrd,var4: word,data1段公共数据var1dw?数据1发送代码段假设CS:代码,DS:数据1开始:移动AX,数据1 MOV DS,AX DW2移动AX,VAR2VAR2的段地址在DS,MOV AX,段

14、var3中;ES是段地址MOVES,AX MOVBX,ES:VAR3 MOVEX,SEG VAR4 MOV ES,AX MOVCX,es: var4call VAR3 PRT srout,代码ends start end start ZK) ht5ss模块2:公共var2data1段公共dat var2dw?数据1 NDS,模块3:公共变量3,变量4数据2分段变量3DW?DATA2ENDS DATA3SEGMENT VAR4DW?data 3 ends publications rout code 1 segment假定cs:code 1 sroutproc far ret sroutendp

15、 code 1 ends end,上述第二个问题主要是段寄存器的管理。当不同模块中的相关段连接成同一个段时,问题非常简单。无论哪个模块访问段中的变量,段寄存器的内容都可以保持不变。例如,在示例5.1.2中,为了访问DATA1段中的变量VAR2,它们的段地址在模块1或模块2中是相同的,因此这两个模块中的DS中的内容不需要改变。然而,当不同模块中的某些段在连接后不在同一段中时,必须注意段寄存器内容的正确设置。例如,当访问例5.1.2中模块1中的变量VAR3或VAR4时,首先取出它们的段地址,并将它们发送到相应的段寄存器。由于变量VAR3和VAR4不在模块1中,有两种方法可以获得相应变量的段地址,如

16、示例5.1.2和5.1.3所示。示例5 . 1 . 3 #;模块1: codata段公共扩展var1: word,var2: byte codata ends data段db?数据段代码段,假设CS: CODE,DS: DATA,ES: CODATA START:MOV AX,数据MOV DS,AX MOV AX,CODATA MOV ES,AX MOV BX,VAR1 MOV VAR2,DL代码段结束START,模块2: codata段公共VAR1,VAR2 VAR1DW?VAR2DB?在示例5.1.2的模块1中,我们使用属性运算符(SEG)来获取VAR3和VAR4的段地址。在示例5.1.3中,给出了另一种方法,因为模块1中要访问的变量VAR1和VAR2不在该模块的数据部分。为了获得这两个变量的段地址,我们在模块1中定义了一个

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论