《汇编-第7章.ppt》由会员分享,可在线阅读,更多相关《汇编-第7章.ppt(67页珍藏版)》请在三一文库上搜索。
1、第七章 宏汇编,7.1 宏指令 7.2重复汇编 7.3条件汇编,7.1宏指令 在汇编语言源程序中,有的程序段在整个程序中要多次出现。有的出现可能是完全不修改的重复,有的可能是仅修改程序段中某些操作数字段,而程序段的功能并无大的变化。为了使在源程序中不重复编写这个相同程序段,我们可以将这个程序段定义成一个“指令”,叫做宏指令。这样,在书写源程序时,可以简单地用宏指令名来代替原来的程序段,使源程序更加简洁、易读。例如在某个源程序中要多次用到对AX、BX、CX、DX的压栈,则可事先编写如下宏指令。 PUSHREG MACRO,PUSH AX PUSH BX PUSH CX PUSH DX ENDM
2、则在后面的程序中,凡是需要对AX、BX、CX、DX的压栈的地方,就可以用PUSHREG来替代。,7.1.1 宏功能的使用过程 使用宏指令必须按照宏定义、宏调用、宏展开三步进行。 一、宏定义 应用宏指令之前,必须首先进行宏定义。用MACRO和ENDM伪指令进行宏定义。MACRO表示宏定义的开始,ENDM表示宏定义的结束。其格式有以下两种: (1)不带参数的宏定义: 宏名 MACRO,: 宏体 : ENDM (2)带参数的宏定义: 宏名 MACRO 形参1,形参2,,: 宏体 : ENDM 上述两种宏定义中,宏体是由若干语句序列组成的程序段。宏名就是给宏体中程序段指定一个符号名,亦是以后宏指令语句
3、中调用该宏体直接引用的符号名。宏名在整个程序中应是唯一的。 不带参数的指令在每次宏调用时只需引用宏名,在宏展开时宏体内各语句序列均不作任何修改。,带参数的指令允许在宏调用中做适当修改,在宏定义中,把允许修改的部分用形式参数(简称形参)来表示,当宏调用时就用相应的实在参数(简称实参)来取代形式参数。形参可以是多个,各个形参之间用逗号相隔。例如对两个字节单元内容相互交换的程序段进行宏定义: EXCHANGE MACRO MEM1,MEM2,REG MOV REG,MEM1 XCHG REG,MEM2 MOV MEM1,REG ENDM,在上述宏定义中,有三个形参:MEM1、MEM2、REG,其中前
4、两个表示将要进行交换的两个存储单元,最后一个参数表示实现两个存储单元数据进行交换时使用的寄存器。 宏定义可以进行嵌套。这时,宏体中语句序列除指令语句、伪指令语句外,可以是另一个已经定义的宏名。 二、 宏调用 经过宏定义,在源程序中任意位置可以调用宏指令。 宏调用格式: 无参数宏调用: 宏名,带参数宏调用: 宏名 实参1,实参2, 例如:对前面两个宏定义的调用: . . . PUSHREG .,. . EXCHANGE BY1,BY2,AL . . :,EXCHANGE DA_BYl,DA_BY2 : 宏汇编程序对带参数宏调用, 用第一个实参替代第一个形参, 第二个实参替代第二个形参, 以此类推
5、。 因此,当实参是多个时, 实参的排列顺序要与形参的排列顺序一致. 若实参的个数比形参多,则多余实参自动被略去,若实参个数比形参少,那么多的形参自动用“空白串“替代.,三、 宏展开 当宏汇编程序扫描到宏指令语句(即宏调用)时,宏汇编程序就把宏定义中宏体的程序段目标代码插在宏指令语句的位置上以替代宏指令语句。若是带参数的宏调用,则同时用相应的实参代替宏体中对应形参的位置,并对原有宏体代码作修改。这样,在程序的目标代码中,每个宏指令语句位置上都包含相应宏体的目标代码,此宏指令的使用不会减少程序的目标代码长度。下面是一个源程序的列表文件,它展示了宏定义,宏调用和宏展开的全部过程。在列表文件中,左边带
6、“+”号的指令是宏汇编程序在宏展开时自动生成的指令。宏定义本身不生成任何目标代码,宏指令语句(即宏调用)本身也不生成目标代码,它仅表示宏调用出现的位置。列表文件如下: ;宏定义,INPUT MACRO MOV AH,0lH INT 2lH AND AL,0FH ENDM ;宏定义,EXCHANG MACRO MEM1,MEM2,REG MOV REG,MEM1 XCHG REG,MEM2 MOV MEM1,REG ENDM ;设置数据段 DATA SEGMENT,BYl DB 10H BY2 DB 20H DATA ENDS ;设置堆栈段 STACK1 SEGMENT PARA STACK D
7、W 20H DUP(0),STACK1 ENDS ;设置代码段 CODE SEGMENT ASSUME CS :CODE,DS:DATA,SS:STACKl START MOV AX,DATA MOV DS,AX,: INPUT ;宏调用语句 + MOV AH,01H + INT 21H + AND AL,0FH EXCHANGE DA_BY1,DA_BY2 ;宏调用语句,+ MOV AL, BY1 + XCHG AL, BY2 + MOV BY1,AL : CODE ENDS END START,712 宏操作符 一、文本操作符 在宏调用时,有时一个实参是由字符、空格或逗号组成,如“WORD
8、 PTR DA_BYTE”。这时把带空格或逗号的实参用“”括起来,以表示它是一个完整的单一的实参。例如对于前面两个存储单元的内容相互交换的冬定义,在宏调用时可以使用文本操作符: EXCHANGE ,AL则在宏展开时,替换的三条指令是: MOV AL,BYTE PTR DA_WORD1 XCHG AL,BYTE PTR DA_WORD2 MOV BYTE PTR DA_WORD1,AL 二、连接操作符 连接操作符&在宏定义中使用时,它可以在形参的前面,也可以在形参的后面。在宏展开时,对应形参的实参就与它前面或后面的符号连接在一起构成一个新的符号。这个连接的功能对修改某些符号很有用。 例如进行移位
9、操作的宏定义和宏调用: ;宏定义 SHIFT MACRO VAR,REG,SHF,NUM,DEST MOV REG,VAR MOV CL,NUM SLSHF REG,CL MOV DEST,REG ENDM ;设置数据段 DATA SEGMENT DA_BYTE DB 12H DA_WORD DW 3400H CONT DB 2,3 DESTl DB 10H DUP(?) DATA ENDS :,;宏调用 SHIFT DA_BYTE,AL,HL,CONT,DEST1 ;宏展开 + MOV AL,DA_BYTE + MOV CL,CONT + SHL AL,CL,+ MOV DESTl,AL ;
10、宏调用 SHIFT DA_WORD,AX,AR,CONT+1, ;宏展开 + MOV AX,DA_WORD + MOV CL,CONT+1 + SAR AX,CL,+ MOV WORD PTR DESTl+2,AX : 宏调用时,形参SHF用HL或AR实参代替。这时,宏汇编程序把S与实参直接连接起来,构成SHL或SAR指令助记符。 三、字符操作符 格式:!字符 操作符!告诉宏汇编程序,“!”符号后面的字符不作特别的操作符使用,而是以字符本身的意义进行处理。如“!&”表示&不作连接操作符,只作为符号&使用。,例:宏定义如下: CHARJL MACRO NUM,CHAR CHARJL&NUM DB
11、 &CHAR& ENDM 宏调用:CHARJL 25,125 宏展开:CHARJL25 DB EXPRE125 其中宏调用的实参中有一个“!”,它表示后面的“”不是文本操作符的结束符,而是一个大于号,713 局部符号伪指令LOCAL 如果在一个宏定义中含有变量名或标号,且它在同一源程序中又多次被宏调用,那么宏汇编程序在宏展开时,将产生多个相同的变量名或标号。这不满足变量名和标号在同一程序中必须是唯一的要求,从而产生汇编出错。 为了避免宏展开时标识符的重复定义, 可用局部符号伪指令LOCAL。它的格式为: LOCAL 符号表,符号表是宏定义中的变量名和标号,多个符号之间用逗号间隔。这些变量名或标
12、号在宏展开时,自动生成格式为“?XXXX”的符号。其中后四位依次十六进制的正整数0000,0001,0002,FFFF。这样保证了在源程序中,多次宏调用时生的变量名或标号的唯一性。例如某源程序要多次实现无符号数乘法运算,即: (MULT1)*(MULT2)MULT3 现用连续相加的办法编制一宏定义MULTIP。在宏定义中有标号,因此使用LOCAL伪指令,使宏定义中的标号在宏展开的程序段中自动生成标号。源程序编制如下:,MULTIP MACRO MULT1,MULT2,MULT3 LOCAL LOP,EXITO MOV DX,MULT1 MOV CX,MULT2 MOV AX,0 JCXZ NE
13、XT,LOP: ADD AX,DX LOOP LOP NEXT: MOV MULT3,AX ENDM DATA SEGMENT DAl DW 12H,56H,DA2 DW 20H,10H DA3 DW ? ,? DATA ENDS STACKl SEGMENT PARA STACK DW 20H DUP(0) STACK1 ENDS,CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKl START: MOV AX,DATA MOV DS,AX MULTIP DAl,DA2,DA3;宏调用 ;宏展开,+ MOV DX, DA1 + MOV CX,DA2 +
14、XOR AX,AX + JCXZ ? 0001 + ? 0000: ADD AX,DX + LOOP ? 0000,+ ? 0001: MOV DA3,AX MULTIP DA1+2,DA2+2,DA3+2 + MOV DX,DAl+2 + MOV CX,DA2+2 + XOR AX,AX + JCXZ ? 0003,+ ? 0002 ADD AX,DX + LOOP ? 0002 + ? 0003 MOV DA3+2,AX MOV AH,4CH INT 21H CODE ENDS END START,714 宏库 有时我们花费许多精力编写了一些好的“宏”,希望这些“宏”能为较多的“程序”服务
15、,不必每次在源程序中重复编制一个宏定义。这时,可以把若干宏定义组成一个宏库,以文件形式供其他源程序调用。例如在MACRO.LIB文件中包括有下面三个宏定义: ;定义宏 INPUT INPUT MACRO MOVE AH,01H INT 21H,AND AL,0FH ENDM ;定义宏OUTPUT OUTPUT MACRO ADDR MOV DX,OFFSET ADDR MOV AH,09H INT 21H,ENDM ;定义宏MULT MULT MACRO MULTl,MULT2,MULT3 LOCAL LOP,NEXT MOV DX,MULTl MOV CX,MULT2 XOR AX,AX,J
16、XCXZ EXITO LOP: ADD AX,DX LOOP LOP NEXT: MOV MULT3,AX ENDM 当某源程序需要调用MACRO.LIB文件中已定义的宏时,可在源程序中使用伪指令INCLUDE。伪指令的使用格式如下: INCIUDE 文件名,宏汇编程序遇到一个INCLUDE伪指令时,便打开它指定的文件,并处理每个宏定义的各语句,直至处理完毕。这样,在源程序中若需宏调用该文件中含有的宏定义,那么如同在源程序中自己已进行宏定义样。例如: INCLUDE MACRO.LIB STACK1 SEGMENT PARA STACK DW 20H DUP(0) STACKl ENDS,DA
17、TA SEGMENT STRl DB INPUT CHAR :$ STR2 DB 0DH,OAH, OUTPUT STRING: BUF DB 10H(),24H DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK1,START: MOV AX,DATA MOV DS,AX OUTPUT STR1 MOV DI,OFFSET BUF MOV CX,10H LOP1: INPUT MOV D1,AL,INC DI LOOP LOPl OUTPUT STR2 MOV AH,4CH INT 21H COSEG ENDS END START,7
18、15 宏嵌套 宏也可以嵌套,宏汇编程序可以处理两种情况的嵌套:宏定义嵌套宏定义和宏定义嵌套宏调用。 一、定义中嵌套宏定义 例如:DEFN MACRO OPA,OPAT OPA MACRO DA1,DA2,DA3,PUSH AX MOV AX,DA1 OPAT AX,DA2 MOV DA3,AX OPO AX ENDM,ENDM 其中,OPA是内层宏定义的宏名,也是外层宏定义的形参,当调用外层宏定义DEFN时,就形成了对内层宏的定义。 如有宏调用:DEFN ADDITION,ADD 经宏汇编后,展开为 ADDITION MACRO DA1,DA2,DA3,PUSH AX MOV AX,DA1 A
19、DD AX,DA2 MOV DA3,AX OPO AX ENDM,也就是说,经过上述宏调用后,定义了一个新的宏ADDITION,此宏的功能相当于DA3DA1+DA2。 二、在宏定义中嵌套宏调用 这种情况要求被调用的宏必须是已定义的,这种情况的嵌套,可以简化宏定义。 例如: DIFN1 MACRO NUM1,NUM2,MOV AX,NUM1 SUB AX,SUM2 ENDM DIFN2 MACRO DA1,DA2,RESULT PUSH AX DIF DA1,DA2,IMUL MOV RESULT,AX POP AX POP DX ENDM 716 宏指令与子程序的区别,宏指令是用一条宏指令来代
20、替一段程序,以简化源程序的书写,自程序也有类似的功能,那么,两者之间有何区别呢? 1、 宏指令是为了简化源程序的书写,汇编程序在处理宏指令时,把宏体插入到宏调用处,所以在源程序中有几次宏调用,就要将宏体插入几次,因此并没有减少代码,没有节约内存。 而子程序是执行时由CPU处理的,若在一个主程序中多次调用一个子程序,在目标代码中,也只是有几个子程序调用指令的代码,而子程序的代码只有一个,因此,使用子程序可以减少代码,节约内存。,2、 子程序的每次调用都需要保护断点、保护现场,在返回时还需要恢复现场、恢复断点,因此执行时间长,速度慢。而宏指令恰恰相反。 所以,当要代替的程序段不长时,速度是主要矛盾
21、,建议使用宏指令。当要代替的程序段比较长时,内存空间是主要矛盾,建议使用子程序。,7.2 重复汇编 重复汇编是指在源程序汇编期间对一些汇编指令序列进行多次汇编。重复汇编伪指令可以出现在宏定义中,也可以单独出现在源程序中。重复汇编是在程序汇编期间对某些语句序列进行重复的汇编,而不是在程序运行期间执行重复操作。重复汇编伪指令有以下三种: 721 定重复REPT 格式: REPT 表达式 (重复语句序列) ENDM 含义:将重复语句序列重复汇编,表达式的值就是REPT与ENDM之间的语句序列重复汇编的次数。,例:用重复汇编可以在81个连续字节单元中存放在一九九表的数值: N0 REPT 9 NN+l
22、 M0 REPT 9 MM+1,DB M * N ENDM ENDM 上述的重复汇编语句序列,经过汇编以后的结果与下列数据定义语句序列的结果一样。 DB 1,2,3,4,5,6,7,8,9 DB 2,4,6,8,10,12,14,16,18 DB 3,6,9,12,15,18,21,24,27,DB 4,8,12,16,20,24,28,32,36 DB 5,10,15,20,25,30,35,40,45 DB 6,12,18,24,30,36,42,48,54 DB 7,14,21,28,35,42,48,56,63 DB 8,16,24,32,40,48,56,64,72 DB 9,18,
23、27,36,45,54,63,72,81,722 不定重复IRP 格式: IRP 形参, ( 重复语句序列) ENDM 含义:将重复语句序列重复汇编,重复汇编次数由尖括号括起来的实参个数所决定。每重复汇编语句序列一次,用一个实参替代形参,第一次用第一个实参,第二次用第二个实参,直到实参用完为止。例如:,NUM5 IRP M, DB NUM * M ENDM 这些语句经过汇编后,把5,0AH,0FH,14H,19H等数据分配给连续的5个字节单元,它等效于以下语句序列: DB 5,DB 0AH DB 0FH DB 14H DB 19H 如果个源程序中要多次把AX、BX、CX寄存器的内容压入堆栈,那
24、末可以用一个宏定义:,PUSHREG MACRO IRP REG, PUSH REG ENDM ENDM 这样,每次宏调用PUSHREG时,宏汇编程序宏展开为下面四条指令:,PUSH AX PUSH BX PUSH CX PUSH DX 723 不定重复字符IRPC,格式: IRPC 形参,字符串 (重复语句序列) ENDM 含义:将重复语句序列重复汇编,重复次数有字符串个数来决定,每次汇编重复语句序列时,依次用字符串中一个字符替代形参,直到字符串替代完毕。例如: IRPC CHR,ABCDEFGH DB &CHR&,ENDM 经过汇编后,可在连续字节单元中产生字符串“ABCDEFGH”的AS
25、CII码。它等效于: DB ABCDEFGH 例如,有AX、BX、CX、DX压入堆栈的宏定义,对应的应从堆栈中弹出四个字,并分别送入DX、CX、BX、AX、可以另有宏定义: POPREG MACRO IRPC REG,DCBA POP REG&X ENDM ENDM,7.3 条件汇编 条件汇编是指汇编程序根据条件的不同汇编不同的程序段。宏汇编程序在汇编有条件汇编语句时,宏汇编程序首先测试语句指定的条件,若条件成立,则汇编它指定的程序段,产生目标代码,若条件不成立,则舍去它指定的程序段,不产生目标代码。通常在汇编语言程序任何位置上可出现条件汇编语句,但是大多数条件汇编是出现在宏定义中。同重复汇编
26、一样,条件汇编仅在程序汇编期间判断条件并进行汇编或不汇编,而不是在程序的执行期间进行。条件汇编语句的基本格式是: IFXX 表达式,条件语句块1 ELSE 条件语句块2 ENDIF,IF语句后面的“XX”是指定的条件(见表7.1)。如果IFXX指定的条件成立,宏汇编程序便把的语句序列汇编成相应的目标代码,否则就把的语句序列汇编成相应的目标代码。ELSE是任选部分,如果没有ELSE,那么,IFXX指定的条件满足就汇编,否则就不汇编。例如,下面给出一个包含在宏定义中的条件汇编: 例:IF伪指令的使用 INCRE MACRO SOURCE,DEST IFE 1-TYPE SOURCE INC SOU
27、RCE MOV AL,SOURCE MOV DEST,AL ENDIF,IFE 2-TYPE SOURCE ADD SOURCE,2 MOV AX,SOURCE MOV DEST,AX ENDIF IFE 4-TYPE SOURCE ADD WORD PTR SOURCE,4,ADC WORD PTR SOURCE+2,0 MOV AX,WORD PTR SOURCE MOV DEST,AX MOV AX,WORD PTR SOURCE+2 MOV DEST+2,AX ENDIF ENDM 上述宏定义的功能是根据SOURCE的类型完成对SOURCE加1、2或加4,然后把相加的结果传送给操作数DEST。如果SOURCE是用DB指令定义的,就对SOURCE加1,如果SOURCE是用DW指令定义的,就对SOURCE加2,如果SOURCE是用DD指令定义的,就对SOURCE加4。,Thank you very much !,本章到此结束,谢谢您的光临 !,
链接地址:https://www.31doc.com/p-2909478.html