200 likes | 398 Views
第 8 章 高级语言汇编技术 ◆ 宏汇编 ◆ 重复汇编 ◆ 条件汇编伪指令. 8.1 宏汇编. 在编写汇编语言程序的过程中,有时某个程序段要出现许多次,有时只是参数不同,但功能完全一样,则这样的程序段可以定义成一个指令,并且称它为宏指令。 8.1.1 宏定义 若想在汇编语言中使用宏指令,就要定义一个宏。按照是否使用参数,可以将宏指令分为如下两种格式。 1. 不带参数的宏定义 宏指令名 MACRO ┇ 宏体 ENDM. 2.带参数的宏定义:
E N D
第8章 高级语言汇编技术◆宏汇编◆ 重复汇编◆ 条件汇编伪指令
8.1宏汇编 在编写汇编语言程序的过程中,有时某个程序段要出现许多次,有时只是参数不同,但功能完全一样,则这样的程序段可以定义成一个指令,并且称它为宏指令。 8.1.1 宏定义 若想在汇编语言中使用宏指令,就要定义一个宏。按照是否使用参数,可以将宏指令分为如下两种格式。 1.不带参数的宏定义 宏指令名 MACRO ┇ 宏体 ENDM
2.带参数的宏定义: 宏指令名 MACRO 形参1,形参2,… ┇ 宏体 ENDM 【例8.2】将两个存储单元数据交换的程序段定义成一个宏指 令EXCH_MEM。 EXCH_MEM MACRO MEM_1,MEM_2,REG MOV REG,MEM_1 XCHG REG,MEM_2 MOV MEM_1,REG ENDM MEM_1,MEM_2,REG是形式参数,形参可以是多个,各个形参 之间用逗号相隔。对于带参数的宏定义,宏体中程序段有些部分允 许宏调用时作适当修改。在宏定义中,把允许修改的分用形式参数 (简称形参)来表示,当宏调用时就用相应的实参数来取代。
8.1.2 宏调用和宏展开 1.宏调用 在汇编语言中使用已定义过的宏指令,称 为宏调用。按照宏指令定义的格式,宏调用也 可分为两种格式。 (1) 无参数宏调用:宏指令名 (2) 带参数宏调用:宏指令名 实参1,实参2,…
2. 宏展开 当宏汇编程序扫描到宏指令语句(即宏调用)时,宏汇编程序就把宏指令定义中宏体的程序段代码替代宏指令语句。若是带参数的宏调用,则同时用相应的实参替代宏体中对应形参的位置,并对原有宏体代码作修改。 下面是一个源程序的列表文件,它展示了宏定义、宏调用和宏展开的全部过程。在列表文件中,左边带“+”号的指令是宏汇编程序在宏展开时自动生成的指令。宏定义本身不生成任何目标代码,宏指令语句本身也不生成目标代码,它仅表示宏调用出现的位置。
EXCH_MEM MACRO MEM_l,MEM_2,REG MOV REG,MEM_1 XCHG REG,MEM_2 MOV MEM_1,REG ENDM DATA SEGMENT DA_W1 DW 55AAH DA_W2 DW 6688H DATA ENDS CODE SECMENT ASSUME CS:CODE,DS:DATA,SS:STACK START: MOV AX,DATA MOV DS,AX ┇ ;宏调用和宏展开 EXCH_MEM DA_W1,DA_W2,AX ;宏指令语句 + MOV AX ,DA_Wl + XCHG AX,DA_W2 + MOV DA_W1,REG ┇ MOV AH,4CH INT 21H CODE ENDS END START
8.1.3 宏调用中的参数使用 为了宏定义和引用的某些特殊需要,有时实参是由字符、空格等特殊符号组成的,因此汇编程序支持几个具有特定含义的运算符。 1.连接运算符& 在宏定义中,如果形式参数与其它字符连接在一起,或形式参数出现在字符串之中,那么,就必须使用连接运算符(&)。在宏指令定义的具体使用时,连接操作符&可以在形参的前面,也可在形参的后面。在宏指令展开时,对应形参的实参就与它前面或后面的符号连接在一起构成一个新的符号。
【例8.3】宏指令SHIFT_N功能是:对某一个寄存器进行由COUNT确定的移位次数,由DIRECT确定逻辑或算术左/右移位,移位的方向可通过&将S和DIRECT对应的实参连接起来。【例8.3】宏指令SHIFT_N功能是:对某一个寄存器进行由COUNT确定的移位次数,由DIRECT确定逻辑或算术左/右移位,移位的方向可通过&将S和DIRECT对应的实参连接起来。 SHIFT_N MARCO REG,DIRECT,COUNT MOV CL,COUNT S&DIRECT REG,CL ENDM 如SHIFT_N BX,HR,3的宏指令的展开为: + MOV CL,3 + SHR BX,CL 这样就实现了使BX逻辑右移3位。形参DIRECT被实参HR代替,通过连接符&将S和HR连接成SHR。同理SHIFT_N AX,HL,5可实现AX逻辑左移5位。
2. 文本操作符< > 文本操作符是一对尖括号<>,用它括起来的内容将作为一个字符串来进行形式参数的整体替换。在宏引用时,如果实参内包含逗号、空格等间隔符,则必须使用该操作符,以保证实参的完整性。如果实参是某个具有特殊含义的字符,为了使它只表示该字符本身,也需要用该运算符括起来。 NUMBER MACRO THEDATA DB THEDATA ENDM 假设在程序中调用此宏指令: DATA SEGMENT NUMBER <1,3,5> DATA ENDS 则宏展开为: DATA SEGMENT + DB 1,3,5 DATA ENDS 如果不加< >,则在宏展开为: + DB 1 ; 而3,5按规则被忽略
3.表达式操作符% 进行宏调用时,如要在实参中使用“%”,则在宏指令调用时宏汇编程序将获取“%”后常数表达式的值作为参数,而非表达式本身,如: NUMBER MACRO X,Y,Z, DB X,Y,Z ENDM 若宏调用为: I EQU 10 J EQU 50 NUMBER 16,%I+J,%J-I 则相应的宏展开为: + DB 16,60,40
4.字符操作符! 字符操作符!的使用表明,“!”后的字符不是特殊字符,而是普通字符。这样对于包含在“<”、“>”、“!”、“%”之间的文本串,汇编程序将能以普通字符处理。如将“!”作为普通字符,则使用!!。 例如宏指令定义: DEFIN_ST MACRO STRING DB ‘&String&S’ ENDM 则宏调用: DEFIN_ST <Please Input a Integer(!>0):$> 其宏展开为: + DB ‘Please Input a Integer(>0):$’
8.1.4 宏嵌套 宏指令定义中还含有宏定义或者是宏指令的定义中含有宏调用,这两种情况都称为宏嵌套。 1. 宏定义中嵌套宏定义 ABCD_1 MACRO ┇ ABCD_2 MACRO ┇ ENDM ┇ ENDM 【例8.4】宏指令定义中嵌套宏定义实例 INIT_1 MACRO X,Y,Z SHIFT_&Y MACRO MOV CL,X S&Z Y,CL ENDM ENDM 如采用下面的宏调用: INIT_1 2,BX,AR ;即将BX算术右移2位的宏指令 则相应的宏展开为: + SHIFT_BX MACRO + MOV CL,2 + SAR BX,CL + ENDM
2.在宏定义中嵌套宏调用 在宏定义中嵌套宏调用的基本形式为:这种嵌套形式比较简单,只需在宏定义中(像在程序中一样)写出宏指令即可。但必须先定义,后调用。 ABCD_l MACRO ;定义一个宏 ┇ ENDM ABCD_2 MACRO ABCD_l ;在宏定义中调用宏 ┇ ENDM
8.1.5 宏汇编中的伪指令 1. MACRO和ENDM 在前面的宏指令的定义中已经介绍过,这是宏操作时必不可少的指令,而且成对出现。 2.PURGE PURGE的功能是取消多个宏定义,即一个宏指令定义可以用伪指令PURGE来取消,然后就再重新定义。 格式: PURGE 宏指令名1 ,宏指令名2…… 取消宏定义的含义是使该宏定义成为空,程序中如果出现一个已被取消宏定义的宏调 用,则汇编程序将不会指示出错,但它将忽略该宏调用,当然也不会予以展开。 3.LOCAL 某些宏定义中存在变量或标号,这些宏定义在同一程序中被多次调用且展开后,就会出现变量或标号重复定义的错误。LOCAL伪指令的使用可以避免此类错误。在宏展开时,让宏汇编程序自动为其后的形参顺序生成特殊符号(范围为??0000—??FFFFH),并用这些特殊符号来取代宏体中的形参,避免了符号重复定义的错误。 格式: LOCAL 形参1,形参2
8.1.6 宏库 8.1.7 宏与子程序的区别 在源程序中,通过书写宏名来引用宏,而子程序是通过CALL指令来调用。 汇编程序对宏通过宏扩展来加入其定义体,宏引用多少次,就相应扩展多少次,所以,引用宏不会缩短目标程序;而子程序代码在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化。 宏引用时,参数是通过“实参”替换“形参”的方式来实现传递的,参数形式灵活多样,而子程序调用时,参数是通过寄存器、堆栈或约定存储单元进行传递的。 宏引用语句扩展后,目标程序中就不再有宏引用语句,运行时,不会有额外的时间开销,而子程序的调用在目标程序中仍存在,子程序的调用和返回均需要时间。 有些宏指令在应用过程中效果较好,因此在以后的汇编语言编程时就不必每次在源程序中重复编制一个宏指令定义,这样也可减少重复编写时的错误,可以把几个宏定义组成一个宏库,以文件形式供其它源程序调用。 返回
8.2 重复汇编 8.2.1 使用REPT伪指令的重复汇编结构 指令格式: REPT 表达式 ┇ 重复语句序列 ENDM 指令以REPT开始,ENDM结束。其中,表达式是REPT与ENDM中间的语句序列需要重复的次数,可以是具体数值,表达式中不能包含有任何外部的或没有定义的项,否则产生错误。 例 REPT重复汇编结构举例 Y=20 REPT 5 Y=Y+10 DB Y ENDM 经汇编后结果如下: DB 30 DB 40 DB 50 DB 60 DB 70
8.2.2 使用IRP伪指令的重复汇编结构 指令格式: IRP 形参,<实参1,实参2,……> ┇ 重复语句序列 ENDM 每次重复汇编语句序列时,就用一个实参替代形参。第一次用第一个实参替代形参,第二次用第二个实参替代形参,直到所有实参用完为止。重复汇编次数由尖括号括起来的实参个数所决定。注意实参必须用尖括号括起来,各个实参之间用逗号分开,如果实参为空,汇编程序则约定跳过IRP与ENDM之间的语句,IRP伪指令的形参只能有一个。 【例8.8】IRP重复汇编结构举例 IRP REG,<AX,BX,CX,DX> PUSH REG ENDM 经汇编展开后为: PUSH AX PUSH BX PUSH CX PUSH DX
8.2.3 使用IRPC伪指令的重复汇编结构 指令格式: IRPC 形参,<字符串> ┇ 重复语句序列 ENDM 每当汇编重复语句序列时,汇编程序将依次用字符串中的一个字符替代形参,直到字符串中的字符替代完毕。重复次数由字符串中字符个数来确定。IIRPC伪指令的形参也只能有一个。 【例8.9】IRPC重复汇编结构举例 IRPC S,ABCD PUSH S&X ENDM 汇编后展开成: PUSH AX PUSH BX PUSH CX PUSH DX 返回
8.3 条件汇编伪指令 PC机有10种条件汇编伪指令,它们是IF、IFl、IF2、IFE、IFDEF、IFNDET、IFB、IFNB、IFIDN、IFNIDN。 一般格式是: IF XX 表达式 ┇ 语句序列1 ELSE ┇ 语句序列2 ENDIF IF与ENDIF必须有,且成对出现,ELSE是可选的,其中IF XX是上述l0种条件汇编伪指令之一,XX为指定的条件,如果指定的条件成立,宏汇编程序将汇编语句序列1,否则汇编语句序列2。 如果没有ELSE,则指定条件成立就汇编,否则就要跳过IF与ENDIF之间的语句序列,IF XX指定的条件参见书中表格。
【例8.10】 条件汇编举例 使用宏指令BRANCH产生一条转向Y的转移指令。当它相对于Y的距离小于128字节时产生JMP SHORT Y;否则产生JMP NEAR PTR Y(Y必须位于该转移指令之后,即低地址区)。 BRANCH宏指令定义: BRANCH MACRO Y IF ($-Y) LT 128 JMP SHORT Y ELSE JMP NEAR PTR Y ENDIF ENDM 现采用宏调用BRANCH Z 则对应宏展开: 设Z与BRANCH指令间的距离小于128时产生: + JMP SHORT Z 否则产生 + JMP NEAR PTR Z 返回