一、一个完整的源程序的结构
一个源程序一般由若干个段组成,每个分段可以是栈段、数据段和代码段。一个源程序可以有多个栈段、数据段和代码段,从语法规则上来看,栈段是有明显标志的;代码段最好的类型为‘CODE’的标记,并用CS作为段界寄存器,只有数据段不要求标志。
完整的源程序的结构一般形式如下:
程序名称;
.
.
.
.
二、源程序的一般的程序:二、简化段的源程序的结构
这种形式只有三个分段;一个栈段、一个数据段和一个代码段。代码长度可达64KB,数据段和栈段是一个组,其总长度可达64KB,组名为DGROUP。组名DGROUP与数据段名@DATA都代表组对应的物理段的段界地址,装入内存时,系统给CS及IP赋初值,使其指向代码段。同时系统还给SS和SP赋初值,使(SS)=DGROUP,(SP)=数据段长度+栈段长度,也就是使栈段为对应的物理段。这样处理是使栈段元素也能用DS寄存器访问,以便于高级语言相连接。
一般模式伪操作符模式
NAME<模块名>;可有可无DOSSEG
TITLE <正文>;可有可无.MODEL SMALL
堆栈段名 SEGMENT PATA STACK’STACK’.STACK [长度]
.DATA
数据语句
堆栈段名 ENDS.CODE
数据段名 SEGMENT .启动标号 MOV AX,DGROUP
MOV DS,AX
执行语句
数据段名 ENDS
代码段名 SEGMENT执行性语句。EXIT
ASSUME 设定段与寄存器的对应关系END
标号:
过程名1 PROC 类型
过程名1 ENDP
过程名N PROC 类型
过程名N ENDP
代码段名 ENDS
END 标号|过程名
三、 基本概念。
(1)汇编程序的分类:自汇编程序和交叉汇编程序;按功能分:浮动汇编程序、微汇编程序、宏汇编。由浮动汇编程序产生的二进制目标代码,可以装入内存在任何位置运行; 微汇编程序只提供将汇编指令转换成机器指令的基本过程,缺乏伪指令处理能力;宏汇编不仅包含一般汇编语言的功能,并且采用了高级语言的数据结构,提供了记录、结构和字符串的操作,提供宏指令、条件汇编、重复汇编、组建宏库等红处理能力及DOS调用等功能。
(2)汇编语言的格式:[名字][前缀]助记符[操作数1],[操作数2]。。。[;注释]
助记符可以是指令、伪指令、宏指令;
<1>名字是以字母(把符号$@?._看成字母)打头且不超过31个字符的字母数字串.有两类:一是事先约定的,不用定义与说明(包括寄存器名字、操作符、伪操作符);二是用户自己定义的名字(包括标号、变量、分段名、组名、过程名、宏定义名、记录名、结构名及域名),名字不能以数字开头,且不能为保留字。
<2>操作符表示语句的主要操作或功能,通常分为做操作符和伪操作符。操作符代真后有目标代码(操作码)对应,其功能有就硬件指令实现;伪操作符代真后没有目标代码对应,其功能由汇编程序实现。(包括完整段操作符、简化段操作符和其他未操作符)。
<3>标号是用:号引入放入名字。标号的属性(标号代表其定义所处位置的地址):1标号的段值属性,就是标号所在的段界地址;其形式有A. 标号,B. SEG 标号。2标号的偏移地址属性,是指标号所处位置的偏移地址;其形式有:A. 标号,B. OFFSET 标号。3标号的类型属性,代表一个值即远标号(FAR)和近标号(NEAR);其形式:TYPE 标号。若为NEAR则TYPE=-1,若为FAR则TYPE=-2。
<4>变量,变量是用数据伪操作符引入的名字。有两种含义一是:代表所表示的变量的值,二是:表示变量所占空间的首地址。变量的属性1 变量的段值属性,是指变量定义所在的段的段界地址;其形式A. 变量
B. SEG 变量。2变量的偏移地址属性值;A. 变量,B. OFFSET 变量。3变量的类型属性,指变量所表示的数据元素的长度(以字节为单位);其形式:TYPE 变量,TYPE变量是一个1—10之间的数字。4变量的元素总和属性,指变量所指数据的元素个数;其形式: LENGTH 变量,只对单项重复子句有意义,其他的LENGTH 变量=1。5变量字节总和属性,变量所指数据所占的储存空间的总字节数;其形式:SIZE 变量,只对单项重复子句有意义,其他的SIZE 变量=1。SIZE=LENGTH X TYPE。
重新定义类型操作符,格式:类型 PTR 表达式;功能:用来为变量或标号建立一个新的属性。对于变量类型可以是TYPE、WORD、DWORD,对于标号可以是NEAR、FAR,表达式可以是变量名、标号或其他地址表达式。
<5>分段名,用伪操作符SEGMENT引入的名字;
其定义形式:分段名 SEGMENT
…………
分段名 ENDS
分段名在使用中代表该分段的段界地址,段值的表示方式:分段名或SEG 分段名
<6>组名,用伪操作符GROUP引入的名字,组名在使用用代表其段界地址。其定义形式:
组名:GROUP 分段名1,分段名2,……
<7>过程名和过程,用伪操作符PROC引入的名字。类型默认为NEAR。其定义形式:
过程名 PROC 类型(FAR/NEAR)
(执行语句)
过程名 ENDP
五、语句是源程序的基本单位。汇编语句按其作用与编译的情况分为:执行语句和说明性语句。
(1)执行语句,编译后有目标程序与之对应。包括:(1)一般执行语句,由操作符定义,一句一般执语句只产生一条目标代码指令;(2)宏语句,由伪操作符定义,包括宏定义、宏调用、宏扩展语句,一个宏语句对应一组目标代码程序。(指令语句)和(宏指令语句)
(2)说明性语句,编译后没有目标程序与之对应。包括(3)数据语句,用于描述数据和给数据赋初值;
(4)列表控制语句,用于说明打印源程序的格式要求;(5)程序结构语句,用于说明源程序的结构;(6)条件汇编语句,用于说明汇编某部分语句时的条件,满足条件则汇编,否则跳过不予汇编(伪指令语句)
(一)执行语句
(1)一般执行语句全部由操作符定义,每一个操作符定义一种语句。包括1数据传语句,2算术运算语句,3比较语句,4转移语句,5字符串语句,6初等函数语句,7置实常数语句,8逻辑操作语句,9控制语句。 其形式有:形式1:[标号:]操作符;形式2:[标号:]操作符地址变量
形式3:[标号:]操作符目地址变量,源地址变量;
形式4:[标号:]操作符目地址变量,源地址变量,直接操作数。
(2)宏语句从功能上分为<1>等价语句,<2>宏定义与宏调用语句,<3>重复块及退出宏展开语句。
<1>等价语句包括:①赋值等价语句,②数值等价语句,③串等价语句。
①赋值等价语句
形式:名字=表达式
其中表达式可以是以整数、常数表达式、地址表达式、一个或两个字符。
功能:汇编时该名字用表达式的值代替。该语句不占内存,必须先定义后使用。名字在语句中作直接操作数使用,并允许重新定义。常用于宏定义、重复模块。
②数值等价语句
形式:名字EQU表达式
其中表达式可以是以整数、常数表达式、地址表达式。名字唯一,不能重定义。功能:汇编时该名字用表达式的值代替。名字在语句中作直接操作数使用, 必须先定义后使用
③串等价语句
形式:名字EQU<字符串>
其中名字可以用另外的字符串定义,但不能用等号定义,也不能作为数值等价语句中的名字。功能:汇编时该名字用其字符串代替。
<2>宏定义
形式:名字 MACRO[AGR1,AGR2,……]
语句串
ENDM
说明:其中的MACRO和ENDM是保留字,‘名字’是宏定义的名字,它可以看作宏命令语句的操作符,实现MACRO和ENDM之间语句串的功能。AGRI(I=1,2,…..)是形式参数,简称形参。
<3>宏调用语句
形式:宏定义名字[A1,A2,…..]
其中宏定义名字是MACRO定义的名字,“A1,A2,….”是宏调用中的实在参数,简称实参。它与MACRO定义的形参相对应。可以是:符号、常数、寄存器等。
<4>宏展开,宏调用语句的展开称为宏展开。宏调用语句是宏定义的应用,汇编时实现宏展开,即把宏定义
的语句串按宏调用提供的实参展开,嵌入到宏调用语句的下面,从而改动了源程
<5>宏嵌套就是宏定义中允许使用的宏调用,但所调用的宏指令必须先定义过,宏定义中还可以包含宏定义。
<6>宏定义中的标号与变量,宏定义中的LOCAL是用来定义局部变量的/标号的,在汇编时将对这些局部变
量/标号赋以新值编号以避免重复,格式:LOCAL 参数表,LOCAL应为宏体中的第一条语句,参数表为宏体中用到的变量/标号。
(二)说明性语句
(3) 数据语句包括一般数据语句和结构数据语句
<1>一般数据语句
形式:[变量]DB|DW|DD|DF|DQ|DT EXP[,EXP]…
其中DB|DW|DD|DF|DQ|DT分别为字节、字、双字、三字、四字、十字,每个元素EXP所占的字节数分别为1、4、6、8、10。.EXP可以是表达式、字符串和?号。
形式:重复次数 DUP (元素值)
其中重复的次数取非零的整数,元素值为数值表达式或?或实数。
<2>数据结构语句包括①记录数据语句、②结构数据语句、③联合数据语句。
① 录数据语句
<1>记录的定义
形式:记录 RECORD 域:宽度[=EXP], 域:宽度[=EXP],……
其中记录和域是用户定义的名字,宽度取1~16间的整数,它表示域所占的二进制位,EXP是相应域的标准值,是可选项。一个记录最长为2个字节。
<2>地址计数器伪指令$,用来表示当前正在汇编指令的地址
<3>ORG伪指令,格式:ORG 表达式,用来指明ORG语句后的程序段的段内起始地址(偏移地址) ② 结构数据语句
<1>结构的定义
形式:结构 STRUC
域 DB 值1
域 DW 值1
域 DT 值1
结构 ENDS
其中,保留字STRUC和ENDS是系统规定的。结构和域是用户自己定义的名字,名字不要重用。飞鸽域的结构可选数据伪操作符定义,用它们的长度表示要求的空间长度。一个结构定义中可用不同长度的域,每个域可以有一项初值或多项初值,但只在有一项初值时能在结构变量中重新赋初值。该形式中‘值1’可省,即不赋初值。
<2>结构上的储存分配和预置;变量定义的格式如下:变量结构名称<>,
<3>对结构的访问,必须使用变量路径名的方法进行,路径名的格式为:变量名。字段名
③ 联合数据语句
<1>联合的定义
形式:联合 UNION
域 DB ?
域 DW ?
域 DT ?
联合ENDS
其中,UNION为保留字,联合与域是用户自己定义的名字。名字一般不要重用,每个域用一个数据伪操作符定义,一般不应有初值。
(4)列表控制语句
<1>印页标题语句
形式:TITLE 字符串
它用于指定没一页上的标题,字符串不能超过60 个字符。汇编取前6个字符作为该模块的名字。省掉该语句时,模块名取源程序名。
<2>页式语句
形式:PAGE [数1][数2]
用于设置程序的页式的形式,标准情况下是每页66行,每行80个字符。数1表示行数,范围10—200,新页从该语句开始计算。数2 表示每行的宽度。
<3>开始输出语句
形式:LIST
系统遇到此语句就输出列表文件。标准情况是设置想此语句的状态,即一般情况下如无此语句则为省掉。只有遇停止输出语句才结束本语句。
<4>停止输出语句
形式:XLIST
系统遇到此语句就停止输出输出它后面的源程序。只有遇开始输出语句才结束本语句。
(5)程序结构语句是伪操作符定义的语句,它们用于说明源程序的终止消息,CPU的类型,分段结构,以及分段内存的安排。
1)模块开始与结束语句
<1>NAME——模块开始语句
形式:NAME[模块名]
功能:表示源程序开始并并指出模块名
说明:NAME省略时,则模块名取源程序中TITKE语句之页标题的前6个字符。如果没有TITLE语句,则取该模块的源程序文件名为模块名。
<2>END—模块结束语句
形式:END[启动标号或过程名]
功能:表示源程序到此结束,并可以指出程序的启动地址,如果有启动号,系统给CS、IP赋初值。 说明模块的一般形式如下:
NAME[模块名]
(所有语句)
END[启动标号或过程名]
2)过程开始与结束语句
<1>过程开始语句(过程语句可以嵌套)
形式:过程名 PROC[类型]…
其中类型为NEAR或FAR,省略时在完整段或简化段的小模式或压缩模式中为NEAR。其他情况为FAR。过程名可以作标号使用.
功能:表示过程的开始
<2>过程结束语句
形式:过程名 ENDP
功能:表示过程的而结束,它与过程开始语句配对使用。
3)指令集选择语句
.8086 选8086(8088)和8087指令集
.186 选80186指令集
.286 选80286非特权指令集及80287指令集,并取消在此语句前使用的.286P的语句对比后语句的作用
.286P选80286专用的特权语句及80286非特权指令集与80827指令集
.386选80386非特权指令集及80387指令集,并取消在此语句前使用.
.386P 选80386专用的特权指令及80386非特权指令集与80387指令集
.8087 选8087指令集,并指定实数的二进制编码为IEEE格式
.287 选80287指令集,并指定实数的二进制编码为IEEE格式
.387 选80387指令集,并指定实数的二进制编码为IEEE格式
.486 选80486非特权指令集,并取消在此语句前使用的.486P的语句对比后语句的作用
.486P 选80486非特权指令集及80487非特权指令集
.NO87 取消协处理器指令集(8087,80387,80387)
.MSFLOAT 关闭协处理器指令集,指定实数的二进制编码为MICROSOFT格式
4)分段定义语句:完整段与简化段
<1>SEGMENT---分段开始语句
形式:分段名 SEGMENT[定位选择][连接类型选择][字长选择][类型标示符]
功能:指出分段名及分段的各种属性,并表示分段开始。
说明:分段名是用户定义的名字,它是不可省的。
A. 定位选择用于指定该段地址的类型。有4种选择类型1.PARA—可省略,表示段始址为16的倍数;2.PAGE---表示段始址为256的倍数;3.WORD--表示段始址为偶数;4.BYTE—表示段始址可为任何字节地址。(这里的段始址指段界地址及偏移地址)
B连接类型。有6种选择方式。1.PUBLIC—表示该连接类型的不同源程序中的同名分段互相连接为一个物理段,统一用该物理段的段界地址为各分段的段界地址,共用一个段寄存器。2.STACK—表示该段为栈段,不同的源程序中的同名栈段连接方式同PUBLIC规定一致,连接后的物理段始址为各同名分段的段始址。系统值其值于SS中,置栈顶于SP中,即(SP)为物理段的段长。3.COMMON—表示连接类型的不同源程序中的同名分段重叠分配,形成统一的物理段,它们有相同的段始址。4.MEMORY—与PUBLIC相同。5.AT数值表达式---表示该分段的段界地址应为指定数值表达式的值,其段始址的偏移址为0.如果没有以上的任何选择,则选分段为独立分段,不与任何分段连接,每一个独立的分段对应一个物理段。
C字长选择。用于定义分段中使用的偏移地址及寄存器的字长。有两种选择1.USE16—表示字长为16位。
2.USE32---表示字长为32 位,即该分段中所有寄存器的长度为32位。
D类型标示符。用于控制段的次序和确定代码段。类型标识符是用单引号括起来的字串,定义的名字不能与该字符串相重,系统要求代码段均使用’CODE’类型标识符。
<2>ENDS—分段结束语句
形式:分段名 ENDS
功能:表示分段到此结束
<3>ASSUME—指定分段寄存器语句
形式:ASSUME 段寄存器:分段名/组名[,段寄存器名:分段名/组名]
功能:指定分段或组段使用的段寄存器,表示使用该伪操作的代码中出现指定段名中的变量时,其变量的段界地址存放于指定的段寄存器中,
说明:栈段必须用SS作为段寄存器。有程序的分段只能够用CS作段寄存器。
各个段寄存器都不写时,可以写成如下: ASSUME NOTHING
<4>GROUP---组名说明语句
形式:组名 GROUP SEG—NAME[,SEG-NAME]…
功能:指定某些分段都分配在一个物理段中。
说明:组名是用户定义的名字,它表示该物理段的段值。SEG—NAME是分段名。
5)简化段定义语句
<1>DOSSEG—段次序语句
形式:DOSSEG
功能:各分段在内存的顺序按DOS段次序排列
<2>.MODEL---内存模式语句
形式:.MODEL模式类型选择[,高级语言]
功能:指示数据及代码允许使用的长度
说明:高级语言可选C、BASIC等,模式类型的可选形式:SMALL—小模式,所有的数据放入一个物理段中,所有的代码放入另外一个物理段中,因而代码分段与数据分段均为NEAR;
MEDIUM—中模式,所有的数据放入一个物理段中,代码可以大于64KB,近、远程均可;COMPZCT—压缩模式,所有数据放入一个物理段,数据可以大于64KB(数据分段占内存不得大于64KB),数据分段为远程,代码为近程;LARGE—大模式。数据与代码均可以超过64KB,代码和数据均允许为远程;HUGE—巨型模式。代码和数据均可大于64KB,数据分段占内存可大于64KB。
<3>.STACK—栈段语句
形式:.STACK[长度(SIZE)]
功能:定义一个栈段,并形成SS及SP初值。(SP)=长度,如果不写长度,则(SP)=1024.隐含的段名为@STACK,定位选择参数为PARA,连接类型选择参数为STACK,类别标识符为’STACK’。
<4>.CODE—代码段语句
形式:.CODE[名字]
功能:定义一个代码分段。一个程序通常只有一个代码分段,如果有多个代码分段,则要用名字区别。一个代码分段时,隐含分段名为@CODE,多分段时,隐含分段名为名字_TEXT,隐含的定位选择为WORD,连接类型为PUBLIC,类别标识符’CODE’。
<5>.DATA—初始化进程数据段
形式:.DATA
功能:定义一个进程数据分段,当用于与高级语言连接时,其数据空间要赋初值。隐含段名为@DATA,定位选择为WORD,连接类型为PUBLIC,类别标识符为’DATA’。
<6>.DATA?—非初始化进程数据段
形式:.DATA?
功能:定义一个近程数据分段,当用于与高级语言连接时,其数据空间只能使用符号?定义数据值,表示不赋值。隐含的段名为@DATA?,定位选择为WORD,连接类型为PUBLIC及类型标识符为’BSS’。
<7>.CONST—常数段
形式:.CONST
功能:定义一个常数分段,该段是近程的,用于与高级语言连用,段中的数据一定不能改变。隐含段名为@CONST
<8>.FARDATA—初始化远程数据段
形式:.FARDATA[名字]
功能:定义一个远程数据段,并且数据语句的数值应赋初值。该语句用于与高级语言连用,当名字省掉时,隐含的段名为@FARDATA ,否则段名为名字。定位选择为PARA,连接类型为独立分段,类别标识符为’FAR_DATA’。
<9>.FARDATA?—非初始化远程数据段
形式:.FARDATA?[名字]
功能:定义一个远程数据段,并且数据语句的数值不赋初值。该语句用于与高级语言连用,当名字省掉时,隐含的段名为@FARDATA ,否则段名为名字。定位选择为PARA,连接类型为独立分段,类别标识符为’FAR_BSS’。
6)其他程序结构语句
<1>ORG—指定地址语句
形式1:ORG 偏移地址形式2:ORG $+偏移地址
功能:形式1表示当前偏移地址(地址计数器$的值)应从该偏移地址开始分配和使用。形式2表示当前偏移地址应再加上所指示的便宜地址。该语句不占内存。
<2>EVEN—偶化语句
形式:EVEN
功能:使当前偏移地址偶化。偏移地址为奇数时加1使其偶化;偏移地址为偶数,则不变。
源程序每行可写80个字符,超过80个,则可以用&续行,一行要写多个语句用!做间隔符,注释用;号。 结构性数据语句可以实现自定义数据结构的伪操作符
(6)条件汇编语句根据某种条件汇编某部分源程序的功能。它的功能由汇编系统实现。条件汇编语句通常在宏定义中使用,使宏定义的使用范围更广。一般情况下,使用条件汇编语句可以使1个源文件产生几个不同的源程序。
1)5组开始语句
<1>是0否条件语句
形式1:IF 表达式
形式2:IFE 表达式
其中,形式2中表达式等于0时为真(满足条件)。形式1中表达式不等于0时为真。表达式中的变量必须在第一次扫描时有确定的值(即不能有向前引用的量)
<2>扫描1否条件语句
形式1:IF1
形式2: IF2
其中,IF1表示在汇编第一次扫描时为真;IF2表示在汇编第二次扫描时为真。该语句用于宏定义。
<3>符号有定义否条件语句
形式1:IFDEF 符号
形式2: IFNDEF 符号
其中形式1当符号有定义时为真,形式2与形式1作用相反。
<4>空否条件语句
形式1:IFB<变量>
形式2:IFNB<变量>
其中形式1中变量为空时真,形式2中变量为非空时为真。必须有<>。该语句只用于宏定义中,以检查形参是否有实参代替,有代替时该形参为‘非空’,否则该形参为‘空’。
<5>字符串比较语句
形式1:IFIDN[1]<字符串1><字符串2>
形式2:IFDIF[1]<字符串1><字符串2>
其中形式1表示字符串1和字符串2相等时为真;形式2和形式1 的作用相反。如果选择I项,则进行字符串比较时不区分大小写,否则要区分大小写,该语句只用于宏定义的中,以比较所传递的两个实参是否相等。
2)一个结束语句
形式:ENDP
表示条件汇编语句段的结束,每个开始语句必须有该结束语句相对应。
3)1个否则语句
形式:ELSE
表示与相应开始语句的条件相反时汇编ELSE之后的语句。该语句不是必须的,如果开始语句没有显示的条件(如IF1或IF2),则不能用ELSE语句。
远过程名指示所在位置的段界地址和偏移地址,近过程名指示偏移地址。