第7章微型计算机汇编语言及汇编程序7.1宏汇编语言的基本语法7.2伪指令7.3宏指令7.4系统功能调用7.5汇编程序的功能及汇编过程7.6汇编语言程序设计习题P153图7.17.1.2常数、变量和标号1.常数(1)二进制数:如01011010B。(2)八进制数:723Q,35O。(3)十进制数:129,129D。(4)十六进制数:如3A5BH,0FH。(5)实数:它由整数、小数和指数3部分组成,±整数部分.小数部分E±指数部分其中,整数和小数部分形成这个数的值,称作尾数,它可以是带符号的数。指数部分由指数标识符E开始,它表示了值的大小,如5.213E-4。(6)字符串常数:‘AB’,在内存中就是41H,42H。在程序中,常数主要出现在:(1)指令语句中源操作数中作立即数,它应与目的操作数的位数相一致,可以是8位或16位,例如:MOVAX,0A5F1H(2)在指令语句的基址加变址的寻址方式中作位移量,例如:MOVBX,[SI+32H](3)在数据定义伪指令中,例如:Aa1DB12H;定义一个字节数据Aa2DW1234H;定义一个字数据Aa3DD12345678H;定义一个双字数据Aa4DB′ABCD′;定义4个字节的字符串数据2.变量(1)变量的定义与预置:定义变量就是给变量分配存储单元,且对这个存储单元赋于一个符号名——变量名,同时将这些存储单元预置初值。定义变量是用数据定义伪指令DB,DW,DD等。例如:VAR-DATASEGMENTDATA1DB12HDATA2DB34HDATA3DW5678HVAR-DATAENDS经过定义的变量,每个变量均有3个属性:①段属性(SEG):表示变量存放在哪一个逻辑段中(即变量所在段的段基值)。②偏移量属性(OFFSET):表示变量在逻辑段中离段起始点的字节数。例如,变量DATA1的偏移量为0,而DATA2的偏移量为1,DATA3的偏移量为2。上述段和偏移量两个属性就构成了变量的逻辑地址。③类型属性(TYPE):表示变量占用存储单元的字节数。这一属性是由数据定义伪指令DB,DW,DD来规定的。变量DATA1,DATA2是用DB定义的,它的类型属性为字节;而DATA3是用DW定义的,类型属性为字;如果用DD定义,类型属性为双字。3.标号标号是一条指令目标代码的符号地址,它常作为转移指令(含子程序调用指令)的操作数。例如:LOP1:……LOOPLOP1JNENEXTNEXT:……与变量类似,每个标号亦具有3个属性:(1)段属性(SEG):(2)偏移量属性(OFFSET)上述两个属性构成了这条指令目标代码首字节的逻辑地址。(3)距离属性:①NEAR(近)②FAR(远)7.1.3表达式与运算符表达式由操作数和运算符组成,在汇编时一个表达式得到一个值。用一个运算符可以对一个操作数或几个操作数进行运算,这就构成了一个表达式,从而得到一个新的值。ASM86中分6类运算符,包括算术运算符、逻辑运算符、关系运算符、分析运算符、组合运算符和分离运算符,它们在汇编时完成相应运算。4.分析运算符(1)SEG求段基址格式:SEG〈符号名〉(2)OFFSET求偏移地址格式:OFFSET〈符号名〉(3)TYPE求符号名类型值格式:TYPE〈符号名〉5.组合运算符组合运算符是用来改变或建立符号名的新类型。(1)定义符号名为新类型格式:〈类型〉PTR〈符号名〉例如,设内存变量D1是字节属性,把它的两个字节内容送到AX中。MOVAX,WORDPTRD1这里的符号名可以是间址、变址寻址、基址加变址寻址表示的存储器操作数。7.2伪指令伪指令没有对应的机器指令,它不是由86系列CPU来执行,而是由MASM-86识别,并完成相应的功能。它在很大程度上规定了MASM-86的性能,因此称之为汇编命令(Directives)。MASM-86中允许使用的伪指令相当丰富,必须搞清楚这些伪指令的功能及其用法,才能编制出高质量的汇编语言源程序。MASM-86中使用的伪指令可分成14类,下面逐一进行介绍。图7.2它与指令语句不同,伪指令语句(又叫命令语句)中的伪指令本身不产生对应的机器目标代码。它仅仅是告诉汇编程序,对后面的指令语句和伪指令语句的操作数应该如何产生机器目标代码。每一条伪指令语句共分4个字段,它的指令格式如图7.2所示。7.1.1伪指令语句格式1.标号名字段这是一个任选字段。标号名后面不能用冒号“:”,这是它与指令语句的突出区别。不同的伪指令,标号名可以是常量名、变量名、过程名、结构名、记录名等。它们可以作为指令语句和伪指令语句的操作数,这时,标号名就表示一个常量或存储器地址。2.伪指令字段这是伪指令语句不可省略的主要成分。伪指令种类很多,如定义数据伪指令DB,DW,DD;段定义伪指令SEGMENT;定义过程伪指令PROC;…。它们是伪指令语句要求汇编程序完成的具体操作命令。3.操作数字段本字段是否需要,需要几个,需要什么样的操作数等都由伪指令字段中伪指令来确定。操作数可以是一个常数(二进制、十进制、十六进制等)、字符串、常量名、变量名、标号、一些专用的符号(如BYTE,FAR,PARA等)。4.注释字段这是一个任选字段,它必须以分号为开始,它的作用与指令语句的注释字段相同。1.符号定义伪指令(赋值语句)(1)〈名字〉EQU〈表达式〉(2)〈名字〉=〈表达式〉该语句把表达式的值赋给符号名,在同一程序中,用EQU语句赋值的符号名不能被重新赋值,但用“=”号赋值的符号名可以被重新赋值。“〈〉”号表示此项不能默认,但该符号不需要输入。例如:Aa=8+22.数据定义伪指令:这种伪指令主要为数据项分配存储单元并预置初值。由这种伪指令构成的语句格式是:DB变量名DW表达式1,表达式2,…DDDQDT其中表达式1,表达式2,…是给变量赋予的初值。表达式可以有如下几种情况:①数值表达式。例如:DA_BYTEDB50H,50DA_WORDDW0A3F1H,4981H变量DA-BYTE的内容为50H,它的下一个字节为32H(即DA-BYTE+1字节单元的内容为十进制50)。DA-WORD字单元内容为0A3F1H(低字节为F1H,高字节为0A3H)它的下一字单元内容为4981H(即DA-WORD+2字单元)。②?表达式:不带引号的?表示可预置任何内容。例如:DA_BDB?,?DA_WDW?,?第1条语句是要求汇编程序分配两个字节单位,第2条语句是要求分配两个字单元。这些单元里现在可以是任意值。③字符串表达式:对于DB伪指令,为字符串中每一个字符分配一个字节单元。字符串必须是用引号括起来且不超过255个字符。字符串自左至右以字符的ASCII码按地址递增的排列顺序依次存放。例如:STRING1DB′ABCDEF′P157图7.3④带DUP表达式:DUP是定义重复数据操作符。在表达式中,使用DUP操作符格式是:DB变量名DW表达式1DUP(表达式2)DD其中表达式1是重复的次数,表达式2是重复的内容。例如:D_B1DB20HDUP(?)D_B2DB10HDUP(′ABCD′)D_W1DW10HDUP(4)第1语句:表示保留20H个字节,每个字节可预置任意内容。第2语句:重复10H个字符串“ABCD”,共占40H字节。第3语句:重复10H个字单元,每单元预置4,共占20H字节。在指令中引用上述定义的符号时,必须考虑符号命的类型,否则会出现错误。D1DB3DUP(12H)例如:MOVAX,D1;D1类型错误MOVAX,WORDPTRD1;正确3.段定义伪指令存储器在逻辑上是分段的,各段的定义由伪指令实现。格式:〈段名〉SEGMENT[定位方式][连接方式][‘类别名’]…〈段名〉ENDS段定义伪指令为程序的汇编和连接说明了段名、分段的各种属性以及分段的开始和结束。段名是自定义符,开始的段名与结束的段名必须相同。段的长度不超过64KB。SEGMENT后面的参数是可选项。例如:dataSEGMENT……dataENDS(1)定位方式(定位类型):定位方式指定段的起始地址边界,方式有4种。PAGE——指定起始地址的低8位是0,即其值能被256整除(称为页边界)。PARA——指定起始地址的低4位是0,即其值能被16整除(称为段边界)。这是系统隐含定位方式。WORD——指定起始地址的最低位是0,即其值能被2整除(称为字边界)。BYTE——指定起始地址是任意值。以上4种边界如下所示:××××××××××××00000000PAGE××××××××××××××××0000PARA×××××××××××××××××××0WORD××××××××××××××××××××BYTE4.段寄存器说明伪指令ASSUME段寄存器:段定义名1[,段寄存器:段定义名2,…]该伪指令告诉汇编程序在汇编时,段寄存器CS:,DS:,SS:和ES:应具有的符号段基址,以便汇编指令时确定段和建立错误信息。但是段寄存器实际值(CS除外)还要由传送指令在执行程序时赋值。例如:ASSUMECS:CODE,DS:DATA5.过程(子程序)定义伪指令格式:〈过程名〉PROC[NEAR](或[FAR])〈过程名〉ENDP过程名是自定义符。定义过程是为实现子程序调用而设的。调用格式为:CALL〈过程名〉过程由RET指令返回,它可以不是最后一条指令,它在过程中可以设多点返回。过程起始名和终止名必须相同。类型NEAR和FAR默认时系统约定是近过程,当选NEAR时,过程是段内调用,过程中的RET是段内返回。当选FAR时,过程是段间调用,过程中的RET是段间返回。例如:STARPROCFAR………STARENDP6.模块开始伪指令格式:NAME模块名该伪指令指明程序模块的开始,并指出模块名。模块名是自定义符,它不能是系统保留字,每次汇编只能出现一次。若该伪指令默认,则取TITLE语句中的页标题前6个字符;若没有TITLE语句,则取源程序文件名为模块名。例如:NAMEEX17.模块结束伪指令格式:END[启动标号或过程名]该伪指令告诉汇编程序源文件结束,并给出执行程序的入口位置。启动地址只有在主模块才有意义。例如:…END8.定位伪指令格式:ORG〈表达式〉该伪指令把以下语句定义的内存数据或程序,从表达式指定的起点(偏移地址)开始连续存放,直至遇到新的ORG指令。表达式的值是一个无符号数。例如:DATASEGMENTA1DB12HORG1000HA2DB24HDATAENDS9.列表伪指令(1)建立标题格式:TITLE标题为列表文件每页第一行定义大标题。(2)建立小标题格式:SUBTTL小标题为列表文件每页定义小标题,输出在大标题之后。(3)自动排版(行数、列数)格式:PAGE行数,行字数为列表文件定义每页行数(10~255)和每行字符数(60~132),默认值是66行,80列。为了简化汇编语言源程序的书写,把一些频繁出现的程序段定义为“宏指令”,当程序中遇到这个程序段时,只需用一条宏调用语句,这样有效地缩短了源程序的长度,使源程序易读,也减少了由于重复书写而引起的错误。从某种意义上讲,它与前述的“过程”有相似之处,也可以将构成一条宏指令的程序段定义为一个“过程”,但两者具有明显的区别,主要表现如下:(1)宏调用语句由宏汇编程序MASM86中的宏处理程序来识别,并完成相应的处理;而调用过程的CALL语句由CPU来执行。7.3宏指令(2)汇编语言源程序在汇编过程中要将宏指令所代替的程序段汇编成相应的机器代码,并插入到源程序的目标代码中,每次调用均要插入,这样,使用宏调用并不能缩短目标代码的长度。但被定义的“过程”经汇编后的机器代码是与主程序分开而独立存在的,其目标代码在存储器中只需保留一份,因此,采用过程调用能有效地缩短目标代码的长度,即节省内存空间,而宏指令却没有这一优点。(3)过程调用时需要保留程序的断点和现场,待过程执行完毕还要恢复现场和断点,这些操作需要耗费CPU的时间,而宏调用则不需进行这些操作。因此,过程调用可节省程序占用的存储空间,但会降低程序的执行速度;而宏调用不能节省存储空间,却能有较快的执行速度