伪指令与源程序格式汇总_第1页
伪指令与源程序格式汇总_第2页
伪指令与源程序格式汇总_第3页
伪指令与源程序格式汇总_第4页
伪指令与源程序格式汇总_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

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

文档简介

1、第4章 伪指令与源程序格式汇编语言程序的语句有三种,即指令、伪指令,还可以有宏指令。关于宏指令将在第7章介绍,本章介绍部分常用的伪指令(又称伪操作)。这些伪指令在程序中是必不可少的,主要用来定义数据变量和程序结构。本章还介绍指令中的操作数和运算符,通过本章的学习,可以学会使用简便而有效率的指令格式,正确定义数据变量,熟知源程序的格式,编写完整的汇编语言程序。4.1 伪指令伪指令和指令不同的是,指令是在程序运行期间由计算机的CPU来执行的,而伪指令是在汇编程序对源程序进行汇编期间由汇编程序处理的操作。它们可以完成如定义数据、定义程序模式、分配存储区、指示程序结束、处理器选择等功能。这里只介绍一些

2、常用的伪指令。有些和宏汇编有关的伪指令在介绍宏汇编时再作说明。4.1.1 处理机选择伪指令由于80x86的所有处理器都支持8086指令系统,但每一种高档的机型又都增加了一些新的指令。为了能使用这些新增指令,在编写程序时要用处理机选择伪指令对所用的处理机作出选择,也就是说,要告诉汇编程序应该选择哪一种指令系统。 处理机选择伪指令有以下几种: .8086 选择8086指令系统 .286 选择8O286指令系统 .286P 选择保护方式下的80286指令系统 .386 选择80386指令系统 .386P 选择保护方式下的8O386指令系统 .486 选择80486指令系统 .486P 选择保护方式下

3、的8O486指令系统 .586 选择Pentium指令系统 .586P 选择保护方式下的Pentium指令系统 指令中的点.是需要的。这类伪指令一般放在整个程序的最前面。如不给出,则汇编程序认为其默认选择是8086指令系统。4.1.2 段定义伪指令我们结合第2章已介绍的程序实例2来看段定义,注意有分号的注释行,程序如下:例4.1datasegment ;定义数据段data string db hello,world!$dataendscodesegment ;定义代码段codeassume cs:code,ds:data ;指定段寄存器和段的关系start:mov ax,data ;对ds赋d

4、ata段基地址mov ds,axmov dx,offset string mov ah,9 int 21h mov ah,4ch int 21hcode ends end start ;汇编结束, 程序起始点start: 1段定义伪指令汇编程序在把源程序转换为目标程序时,必须确定标号和变量(代码段和数据段的符号地址)的偏移地址,连接程序对针目标程序把不同的段和模块连接在一起,确定各个段的段地址。段地址确定了,其中的指令、标号和变量的段地址也就确定了,这样就形成一个可执行程序。为此,需要段定义伪指令。段定义伪指令格式:segment_name SEGMENTsegment_name ENDS其中

5、segment_name由用户确定,大写的为关键字。段定义伪指令两句成对出现,两句之间为其它指令。为了确定用户定义的段和哪个段寄存器的关系,用ASSUME伪指令来实现。ASSUME伪指令格式:ASSUME register_name:segment_name ,register_name:segment_name其中register_name为段寄存器名,必须是CS,DS,ES和SS。而segment_name则必须是由段定义伪指令定义的段中的段名。ASSUME伪指令只是指定把某个段分配给哪一个段寄存器,它并不能把段地址装入段寄存器中,所以在代码段中,还必须把段地址装入相应的段寄存器中。为此,

6、还需要用两条MOV指令完成这一操作。但是,代码段不需要这样做,代码段的这一操作是在程序初始化时完成的。一般情况下,使用上述的段定义伪指令就可以了,如果需要对段定义作进一步地控制,SEGMENT伪指令还可以增加类型及属性的说明,其格式如下: segment_name SEGMENT 定位类型组合类型 使用类型“类别”segment_name ENDS如果需要用连接程序把本程序与其他程序模块相连接时,就需要使用这些说明,具体内容安排在第6章有关子程序的多模块设计中介绍。2简化的段定义伪指令MASM5.0以上版本还支持一种简化的段定义方法,把例4.1程序用简化的段定义方法可以改写如下:例4.2.mo

7、del small ;定义存储模型为small .data ;定义数据段data string db hello,world!$.code ;定义代码段codestart:mov ax,data ;对ds赋data段基地址mov ds,axmov dx,offset string mov ah,9 int 21h mov ah,4ch int 21hend start 首先用.MODEL伪指令说明在内存中如何安排各个段,存储模型为SMALL的意思是:所有数据都放在一个64KB的数据段,所有代码都放在另一个64KB的代码段,数据和代码都为近访问。这是最常用的一种模型。.DATA伪指令用来定义数据

8、段,但没有给出段名,默认段名是_DATA。DATA表示段名_DATA,在指令中表示段地址。简化段定义的表达能力不如SEGMENT伪指令那样完整而清楚,所以很多时候还是用SEGMENT伪指令。有关简化段定义的更多说明在第6章有关子程序的多模块设计中介绍。4.1.3 程序开始和结束伪指令在前面例子中,都没有使用表示程序开始的伪指令。用户根据需要可以在程序的开始用NAME或TITLE伪指令定义该程序模块名。NAME的格式为:NAME module_name其中module_name 为模块的名字。如果程序中没有使用NAME伪指令,也可使用TITLE伪指令来指定模块名,其格式为:TITLE text其

9、中text中的前六个字符被汇编程序作为模块的名字。TITLE伪指令的另一个作用是在列表文件的每一页上打印标题。标题text最多可有6 0个字符。如果程序中既无NAME又无TITLE伪指令,则用源文件名作为模块名。所以NAME及TITLE伪指令不是必要的。表示源程序结束的伪操作的格式为:END label汇编程序将在遇到END时结束汇编。其中标号label指示程序开始执行的起始地址。如果是多个程序模块相连接,则只有主程序需要使用标号,其他子程序模块则只用END而不能指定标号。 4.1.4 数据定义与存储器单元分配伪指令我们知道,指令语句的一般格式是:标号: 操作码 操作数 ;注释 这一类伪指令的

10、格式是:变量 操作码 N个操作数 ;注释 其中变量字段是可有可无的,它用符号地址表示。其作用与指令语句前的标号相同。但它的后面不跟冒号。操作码字段说明所用伪操作的助记符,即伪操作,说明所定义的数据类型。常用的有以下几种:DB 伪操作用来定义字节,其后的每个操作数都占有一个字节(8位)。DW 伪操作用来定义字,其后的每个操作数占有一个字(16位,其低位字节在第一个字节地址中,高位字节在第二个字节地址中,即数据低位在低地址,数据高位在高地址)。DD 伪操作用来定义双字,其后的每个操作数占有两个字(32位)。DF 伪操作用来定义6个字节的字,其后的每个操作数占有48位。DQ 伪操作用来定义4个字,其

11、后的每个操作数占有4个字(64位),可用来存放双精度浮点数。DT 伪操作用来定义1O个字节,其后的每个操作数占有1O个字节,为压缩的BCD码。(需要说明的是,MASM6允许DB,DW,DD,DF,DQ,DT伪操作分别用BYTE,WORD,DWORD,FWORD,QWORD,TBYTE代替)。这些伪操作可以把其后跟着的数据存人指定的存储单元,形成初始化数据;或者只分配存储空间而并不确定数值。下面举例说明各种用法。例4.3 操作数为常数、数据表达式。 D_BYTE DB 10,5,10HD_WORD DW 14,100H,-5,0ABCDHD_DWORD DD 4×8 程序中默认的数据为

12、十进制数,10H为十六进制数,用DB定义的数据的值不能超出一个字节所能表示的范围。数据10的符号地址是D_BYTE,数据5的符号地址是D_BYTE+1。数据可以是负数,均为补码形式存放。允许数据表达式,如4×8,等价为32。当数据第一位不是数字,应在前面加0,如0ABCDH。数据在内存中的存放如图4.1所示。D_BYTE D_WORD D_DWORD 0A05100E000001FBFFCDAB20000000图4.1例4.3的汇编结果 例4.4 操作数为字符串。问号?仅预留空间。数据在内存中的存放如图4.2所示。 MESSAGE DB 'HELLO',? DB AB

13、CDMESSAGE 43454C4C4F-41424344图4.2 例4.4的汇编结果例4.5 用操作符复制操作数。数据在内存中的存放如图4.3所示。 ARRAY DB 2 DUP(1,3,2 DUP(4,5)ARRAY 010304050405010304050405图4.3 例4.5的汇编结果例4.6 指令中使用隐含类型属性。 OPER1 DB ?, ?OPER2 DW ?, ? MOV OPER1, 0 MOV OPER2, 0 MOV OPER2, AX第一条指令将使OPER1字节单元清零,第二条指令将使OPER2字单元清零,因为OPER2为字类型变量,第三条指令两个操作数类型一致,无

14、需说明。例4.7 在指令中使用类型属性操作符指定操作数类型。 OPER1 DB 3, 4OPER2 DW 5678H, 9MOV AX,OPER1MOV BL, OPER2MOV BX, 0前两条指令操作数类型不匹配,第三条指令的目标操作数类型不明确,所以都是错误的。解决的办法是可在指令中对操作数类型作临时性指定,以使操作数类型匹配和明确。这三条指令可改为:MOV AX,WORD PTR OPER1MOV BL, BYTE PTR OPER2MOV BYTE PTRBX, 0使用类型属性操作符WORD PTR,BYTE PTR 可对操作数类型进行重新指定。指令执行结果:AX=0403H,BL=

15、78H。实际上一个变量也可以定义成不同类型,以方便使用。这可以用LABEL伪操作来定义,格式为:name LABEL type例4.8 把变量定义成不同类型,指令中可灵活选用。指令执行结果如图4.4所示。 OPR_B LABEL BYTEOPR_W DW 4 DUP(0)MOV AX, 1234HMOV OPR_B, ALMOV OPR_W+2, AXOPR_BOPR_W 0000000000000000图4.4 (1) 例4.8的数据定义OPR_BOPR_W 3400341200000000图4.4 (2) 例4.8的指令执行结果OPR_B LABEL BYTE伪操作使得OPR_B和OPR_

16、W指向同一个内存单元。4.1.5 表达式赋值伪指令汇编语言程序也允许表达式,以方便程序设计。可以用赋值伪操作给表达式赋予一个名字。其格式如下:Expression_name EQU Expression上式中的表达式必须是有效的操作数格式或有效的指令助记符,此后,程序中凡需要用到该表达式之处,就可以用表达式名来代替了。举例如下:VAL EQU 86 DATA EQU VAL+5 ADDR EQU BP+VAL 此后,指令 MOV AX,ADDR 就代表MOV AX,BP+86,可见,EQU伪操作的引入提高了程序的可读性,也更加易于程序的修改。必须注意:在EQU语句的表达式中,如果有变量或标号的

17、表达式,必须先定义后引用。 另一个更为简洁的赋值伪操作是,格式同EQU,只是用替换EQU。它们之间的区别是EQU伪操作中的表达式名是不允许重复定义的,而伪操作则允许重复定义。例如,VAL=53VAL=VAL+53VAL可以多次被伪操作赋值,而EQU则不允许重复定义。4.1.6 汇编地址计数器与定位伪指令1地址计数器$在汇编程序对源程序汇编的过程中,为了按序存放程序中定义的数据变量和指令,使用16位的地址计数器(location counter)来保存当前正在汇编的指令的偏移地址。当开始汇编或在每一段开始时,把地址计数器初始化为零,以后在汇编过程中,每处理一条指令,地址计数器就增加一个值,此值为

18、该指令所需要的字节数。地址计数器的值可用$来表示,汇编语言允许用户直接用$来引用地址计数器的值。如在指令中引用$,JMP $+8的转向地址是本条指令的首地址加上8。显然$+8必须是另一条指令的首地址,否则汇编程序将指示出错。当$用在伪操作的参数字段时,它所表示的是地址计数器的当前值。例4.9 考察$的作用,假定$初值=0,数据在内存中的存放如图4.5所示。 ARRAY DW 3,$+7,7COU=$NEW DW COUARRAY NEW 0300090007000600图4.5 例4.9的汇编结果2. ORG伪操作ORG伪操作用来设置当前地址计数器的值,其格式为:ORG constant ex

19、pression如常数表达式的值为n,则ORG伪操作可以使下一个字节的地址为n。例4.10 考察ORG伪操作,数据在内存中的存放如图4.6所示。 ORG 0DB 3ORG 4BUFF DB 5ORG $+6VAL DB 9BUFF VAL 03-05-09图4.6 例4.10的汇编结果可以看成是从4号单元开始定义了一个名为BUFF长度为6个字节的键盘输入缓冲区。3EVEN伪操作EVEN伪操作使下一个变量或指令开始于偶数地址。一个字的地址最好从偶数地址开始。例如:EVENARRAY DW 80 DUP(?)4ALIGN伪操作ALIGN伪操作使下一个变量的地址从4的倍数开始,这可以用来保证双字数组

20、边界从4的倍数开始,其格式为:ALIGN boundary其中Boundary必须是2的幂。例如:ALIGN 8ARRAY DW 80 DUP(?)4.1.7 基数控制伪指令汇编程序默认的数为十进制数,所以在程序中使用其他基数表示的常数时,需要专门给以标记如下: (1)二进制数:由一串0和1组成,其后跟以字母B,如00101001B。 (2)十进制数:由09的数字组成的数,一般情况下,后面不必加上标记,在指定了其它基数的情况下,后面跟字母D,例如23D。 (3)十六进制数:由09及AF组成的数,后面跟字母H。这个数的第一个字符必须是09,所以如果第一个字符是AF时,应在其前面加上数字0,如0F

21、FFFH。 RADIX伪操作可以把默认的基数改变为216范围内的任何基数。其格式如下:.RADIX expression其中表达式用来表示基数值(用十进制数表示)。 注意:在用.RADIX把基数定为十六进制后,十进制数后面都应跟字母D。在这种情况下,如果某个十六进制数的末字符为D,则应在其后跟字母H,以免与十进制数发生混淆。4.1.8 过程定义伪指令子程序又称过程,可以把一个程序写成一个过程或多个过程,这样可以使程序结构更加清晰,基本的过程定义伪指令的格式为:procedure_name PROC Attributeprocedure_name ENDP其中过程名(procedure_name

22、)为标识符,起到标号的作用,是子程序入口的符号地址。属性(Attribute)是指类型属性,可以是NEAR或FAR。例4.1的程序段可以改写为过程,见下例:例4.11data segment ;定义数据段data string db hello,world!$data endscode segment ;定义代码段codeassume cs:code,ds:data main proc far ;定义过程mainmov ax,data mov ds,axmov dx,offset stringmov ah,9int 21hmov ah,4chint 21hmain endpcode ends

23、end main ;汇编结束, 程序起始点main该程序的过程部分也可写成:main proc far push ds ;ds进栈mov ax,0 ;0进栈push axmov ax,data mov ds,axmov dx,offset stringmov ah,9int 21hret ;返回 main endp该过程对DOS来说是一个远过程,这里在过程的开始把当前DS的值和0压入堆栈,过程的最后用RET返回到DOS命令状态。这是一个固定用法。RET指令使堆栈中的2个字(0和DS的值)弹出到IP和CS,实际上是执行了该处的退出程序的指令INT 20H。增强功能的过程定义在第六章介绍。但一般情

24、况下,都是使用基本的过程定义。4.2 语句格式程序中用得最多的是指令和有关数据定义的伪指令,这些语句基本上可以由4项组成,格式如下:name operation 0perand ;comment 名字 操作 操作数 ;注释 名字项是一个符号,可以是指令的标号,也可以是变量名。 操作项是一个操作码的助记符,它可以是指令、伪指令或宏指令名。 操作数项由一个或多个表达式组成,它提供该操作所要求的操作数或相关信息。 注释项用来说明程序或语句的功能。 上面带方括号的两项是可有可无的,各项之间必须用空格隔开。下面分别说明各项的表示方法。4.2.1 名字项和操作项1名字项名字项用下列字符来表示: 字母AZ

25、数字O9 专用字符?,·,-,$除数字外,所有字符都可以放在源语句的第一个位置。名字中如果用到·,则必须是第一个字符。名字项可以是标号或变量,用来表示本语句的符号地址。如果是指令的标号,后面跟冒号:。作为一个地址符号,显然应有3种属性:段、偏移及类型。段属性,定义该地址符号的段起始地址,此值必须在一个段寄存器中。偏移属性,偏移地址是从段起始地址到定义该地址符号的位置之间的字节数。对于16位段是16位无符号数。类型属性,对于标号,用来指出该标号是在本段内引用还是在其他段中引用的。如是在段内引用的,则称为NEAR,对于16位段,指针长度为2字节。如在段外引用,则称为FAR,对于

26、16位段,指针长度为4字节(段地址2字节,偏移地址2字节)。对于变量,类型属性定义该变量所保留的字节数。如BYTE(1个字节)、WORD(2个字节)、DWORD(4个字节)、FWORD(6个字节)、QWORD(8个字节)、TBYTE(1O个字节),这一点在数据定义伪操作中已作了说明。 作为一个地址符号,在同一个程序中,显然不能重复定义,即同样的标号或变量的定义只允许出现一次,否则汇编程序会指示出错。2操作项 操作项可以是指令、伪指令或宏指令的助记符。对于指令,汇编程序将其翻译为机器语言指令。对于伪指令,汇编程序将根据其所要求进行处理。对于宏指令,则将根据宏定义展开。有关宏指令的具体内容将在第7

27、章专门介绍。4.2.2 表达式和操作符 操作数项是指令的最复杂最灵活的一项。操作数项由一个或多个表达式组成。对于指令,操作数项一般给出操作数地址,它们通常不超过两个。对于伪操作或宏指令,则给出它们所要求的参数。操作数项可以是常数、寄存器、标号、变量。这些我们已经知道。操作数项还可以是表达式,而表达式是常数、寄存器、标号、变量与一些操作符(运算符)相组合的序列。在汇编期间,汇编程序按照一定的优先规则对表达式进行计算后可得到一个数值或一个地址,如是数值,这个表达式就是数字表达式,如是地址,这个表达式就是地址表达式。那么表达式有哪些操作符呢?下面介绍一些常用的操作符在表达式中的作用。特别注意的是,表

28、达式在汇编阶段起作用,只有正确的表达式才能通过汇编。1算术操作符算术操作符有,*,/和MOD。其中MOD是指除法运算后得到的余数,如7/5的商为1,而7 MOD 5 为2(余数)。要注意的是,算术操作符在表达式中的使用,其结果必须有明确的物理意义时才是有效的,下面举例说明:例4.12 算术操作符的使用设有如下定义:VAL=4DA1 DW 6,2,9,3DA2 DW 15,17,24上面定义的VAL是常数,我们无需确定它的位置就可以使用。DA1和DA2是变量的符号地址,它们在内存中有确定的位置,我们只有根据它们的地址才能访问。MOV AX,DA1*4 ;错,地址乘或除,没有意义MOV AX,DA

29、1*DA2 ;错,地址乘或除,没有意义MOV AX,DA1+DA2 ;错,地址相加,没有意义MOV AX,BX+VAL ;错,BX+VAL须用指令实现MOV AX,BX+VAL ;地址表达式,汇编成MOV AX,BX+4MOV AX,DA1+VAL ;地址表达式,汇编成直接寻址指令,执行后,AX=9MOV AX,VAL*4/2 ;数字表达式,汇编成MOV AX,8MOV AX,VAL*4/2 ;数字表达式,汇编成MOV AX,8 MOV CX,(DA2-DA1)/2 ;地址相减,得到DA1存储区长度,汇编成MOV CX,4 2逻辑与移位操作符逻辑操作符有AND,OR,XOR和NOT;移位操作符

30、有SHL和SHR。它们都是按位操作的。只能用于数字表达式中。逻辑操作符要求汇编程序对其前后两个操作数(或表达式)作指定的逻辑操作。例4.13 逻辑操作符的使用VAL=4MOV AX,BX AND 0FFH ;错,BX AND VAL须用指令实现MOV AX,VAL AND 0F0H ;汇编成MOV AX,0AND AX,VAL OR 0F0H ;汇编成AND AX,0F4H移位操作符的格式是: expression SHI(或SHR) numshift汇编程序将expression 左移或右移numshift位,如移位数大于15,则结果为O。例4.14 移位操作符的使用VAL=4MOV AX,

31、BX SHL 2 ;错,BX 左移须用指令实现MOV AX,VAL SHL 2 ;汇编成MOV AX,10HMOV AX,8 SHL 2 ;汇编成MOV AX,20H 3关系操作符关系操作符用来对两个操作数的大小关系作出判断。六个关系操作符是EQ(相等)、NE(不等)、LT(小于)、GT(大于)、LE(小于等于)、GE(大于等于)。关系操作符的两个操作数必须都是数字,或是同一段内的两个存储器地址。计算的计算结果为逻辑值,如结果为真,表示为0FFFFH;结果为假,则表示为0。例4.15 关系操作符的使用VAL=4MOV AX,BX GT 2 ;错,BX 是否大于2须用指令实现判断MOV AX,V

32、AL GE 2 ;汇编成MOV AX,0FFFFHMOV AX,8 LE VAL ;汇编成MOV AX,0 4数值回送操作符 它主要有TYPE,LENGTH,SIZE,OFFSET,SEG等。下面分别说明各个操作符的功能。(1)TYPE 格式: TYPE expression如果该表达式是变量,则汇编程序将回送该变量的以字节数表示的类型:DB为1,DW为2,DD为4,DF为6,DQ为8,DT为10。如果表达式是标号,则汇编程序将回送代表该标号类型的数值,NEAR为-1,FAR为-2。如果表达式为常数则回送0。(2) LENGTH 格式: LENGTH variable变量用DUP复制的,则回送

33、总变量数,其它为1。(3) SIZE 格式: SIZE variable变量用DUP复制的,则回送总字节数,其它为单个变量的字节数。(4) OFFSET 格式: OFFSET variable或label回送变量或标号的偏移地址。(5) SEG 格式: SEG variable或label回送变量或标号的段地址。例4.16 数值回送操作符的使用设有如下定义:ORG 0VAL=4ARR DW 4 DUP(3)DAT DW 15,17,24STR DB ABCDEF汇编程序对下面的指令汇编结果为:MOV AX,TYPE ARR ;汇编成MOV AX,2MOV AX,LENGTH ARR ;汇编成M

34、OV AX,4MOV AX,LENGTH DAT ;汇编成MOV AX,1MOV AX,SIZE ARR ;汇编成MOV AX,8MOV AX,SIZE DAT ;汇编成MOV AX,2MOV AL,SIZE STR ;汇编成MOV AX,1MOV AX,OFFSET ARR ;汇编成MOV AX,0 5属性操作符它主要有PTR、段操作符、SHORT、THIS、HIGH、LOW、HIGHWORD和LOWWORD等。这类操作符通常在指令执行时起作用。 (1)PTR格式:type PTR expression用类型type 对expression所表达的变量地址赋予另一种属性。(2)段操作符,表示

35、地址的段属性,如指令中使用的段前缀。(3)SHORT,如JMP SHORT P1指令,表示转移地址为短转移。(4)THIS格式:THIS type只是指定一个类型type的操作数,使该操作数的地址与下一个存储单元地址相同。功能和LABEL伪指令类似。(5) HIGH和LOW,HIGHWORD和LOWWORD把一个字的高位/低位字节分离,把一个双字的高位/低位字分离。例4.17 属性操作符的使用设有如下定义:VAL=1234HBUF=THIS BYTE DAT DW 6,12,17因为BUF和DAT的地址相同,但类型不同,则:MOV AL,BUF 和 MOV AL,BYTE PTR DAT两条指

36、令等效。 指令 MOV AH,HIGH VAL 执行后,AH=12H。需要说明的是,在计算表达式时,根据操作符的优先级和括号,从左到右进行计算。下面给出操作符的优先级别,从高到低排列,有11级: (1)在圆括号中的项,方括号中的项,结构变量(变量,字段),LENGTH,SIZE,WIDTH,MASK。 (2)名:(段取代)。 (3)PTR,OFFSET,SEG,TYPE,THIS及段操作符。 (4)HIGH和LOW。 (5)乘法和除法:*,/,MOD,SHL,SHR。(6)加法和减法:+,-。(7)关系操作:EQ,NELT,LE,GT,GE。(8)逻辑:NOT。(9)逻辑:AND。(10)逻辑

37、:OR,XOR。(11)SHORT由于表达式和操作符的规定较多,编程时不必为了一味追求程序的简练而使表达式复杂化,以免出错。4.3.1 EXE文件与COM文件1程序段前缀PSP程序在执行前调入内存时,由DOS确定装入的起始地址,并在此处首先建立一个程序段前缀PSP(Program Segment Prefix),接着装入程序。PSP为256个字节,其中包含很多信息,例如:地址PSP:0存放的是INT 20H(机器码为CD20)。INT 20H指令为程序返回的中断调用。地址PSP:80HPSP:0FFH处存放命令行参数,参数直接提供给可执行程序。如执行程序PROG.EXE,可在DOS提示符下键入

38、:PROG par1,par2这里par1和par2为参数,则命令行参数域为:0bh,“par1,par2” ,0dh。这里0bh表示参数长度,0dh表示回车符。 2 EXE文件前面介绍的源程序都是形成EXE文件的格式,EXE文件允许多个段,可以指定任一条指令为执行的开始地址。EXE文件除了程序本身,还有文件头。文件头由LINK程序生成,其中包括程序的重定位信息,供DOS装入文件时用。例如,在程序中经常用这样的指令来确定段寄存器的值:MOV AX,DATAMOV DS,AX程序在装入前无法确定在内存中的物理位置,LINK后的DATA段地址只是一个相对地址,在程序装入内存时,DOS根据装入的起始

39、地址,把DATA段的相对地址转为绝对地址,再通过执行程序,把DATA段的段地址送DS寄存器。EXE文件装入内存后,有关寄存器的值如下:DS=ES=PSP段地址CS:IP=程序执行的起始地址SS:SP=堆栈段的栈底地址3 COM文件还有一种可执行文件,其扩展名为COM,COM文件由本身的二进制代码组成,它没有EXE文件那样具有文件信息的标题区,在装入内存后,其内容不变,它占用的空间比EXE文件要小得多。COM文件要求源程序只含一个代码段,即CS=DS=ES=SS,所以占用空间不超过64KB,程序中如有过程调用,类型应为NEAR。COM文件要求程序从100H开始执行(前面256字节为程序段前缀)。

40、COM文件的源程序格式举例如下:例4.18;hello1.asm code segment assume cs:code org 100hmain proc near ;也可为far mov ax,cs mov ds,axmov dx,offset stringmov ah,9int 21hmov ah,4ch ;退出程序int 21hstring db hello,world!$main endpcode ends end main例4.19;hello2.asm code segment assume cs:code org 100hstart:mov ax,cs mov ds,axmov

41、 dx,offset stringmov ah,9int 21hint 20h ;退出程序string db hello,world!$code ends end main例4.20;hello3.asm code segment assume cs:code org 100hmain proc far push dsxor ax,axpush ax mov ax,cs mov ds,axmov dx,offset stringmov ah,9int 21hret ;退出程序string db hello,world!$main endpcode ends end main程序需要定义成一个远过程,开始的三条指令把DS和0压入堆栈,程序最后的RET指令,把栈顶的两个字弹出到CS和IP,这就使CS:IP=DS:0,从而执行CS:IP(DS:0)处的指令,而这里正是PSP:0处,其中存放的是INT 20H(机器码为CD20)。4 COM文件的产生并不是具有COM文件的源程序格式,就一定是EXE文件,COM文件也是通过LINK连接程序产生,连接命令后面须加上/T。如:C:MASM6LINK

温馨提示

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

评论

0/150

提交评论