用一个例子来说明宏定义、宏调用和宏展开的情况
例:将两个16位数相加,结果存入16位 RESULT 单元中 。
;对两数相加功能进行宏定义
BCDADD MACRO VARX,VARY,RESULT
MOV AL,VARX
ADD AL,VARY
MOV RESULT,AL
MOV AL,VARX+1
ADC AL,VARY+1
MOV RESULT+1,AL
ENDM
DATA SEGMENT
A1 DW 1234H
A2 DW 5678H
A3 DW ?
B1 DW 1357H
B2 DW 2468H
B3 DW ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
BCDADD A1,A2,A3;宏调用
BCDADD B1,B2,B3 ;再次宏调用
RET
CODE ENDS
END START
经宏展开后:
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV AL,A1
1 ADD AL,A2
1 MOV A3,AL
1 MOV AL,A1+1
1 ADC AL,A2+1
MOV A3+1,AL
1 MOV AL,B1
1 ADD AL,B2
1 MOV B3,AL
1 MOV AL,B1+1
ADC AL,B2+1
MOV B3+1,AL
宏汇编程序在所展开的指令前标识以‘1’号以示区别。较早的版本用‘+’
宏定义中的参数:
1 宏定义可以无参数
savereg macro
push ax
push bx
push cx
push si
endm
2 参数可以是操作码
a macro p1, p2,p3
mov ax,p1
p2 p3
endm
调用:
a word_ var ,inc,ax
展开:
mov ax,word_var
1 inc ax
3 参数可以是操作码或操作数的一部分,但在宏定义体中必须使用分隔符&,即&是操作符,在宏定义中可作为形参的前缀,展开时把&前后的两个符号连接起来,形成操作码、操作数或字符串。&只能出现在宏定义中。
4 伪操作%不能出现在形参的前面,通常用在宏调用中,将跟在它后面的表达式的值转换成以当前基数下的数,在宏展开时,用转换后的值代替形参。
伪指令 LOCAL :
宏定义体内可以使用标号。对于使用了标号的宏定义,若多次调用,势必产生标号的多重定义,汇编时出错。解决这一问题可使用伪指令LOCAL,其一般格式为:
LOCAL 局部标号1,局部标号2,…
宏汇编程序将为标号分别生成格式为“??XXXX”的唯一的符号以代替各局部标号。XXXX代表四位十六进制数0000~FFFF。这样,在汇编源程序中,避免了多次宏调用时生成的标号重复。
注意:LOCAL伪操作只能用在宏定义体内,而且必须是MACRO伪操作后的第一个语句,在MACRO与LOCAL不能出现注释和分号标志。
在宏定义内使用宏:
宏定义中允许使用宏调用,限制条件是:必须先定义
列表伪操作:
Masm提供了.xall , .lall, sall来控制汇编清单中宏展开的列出情况
.xall 为默认情况,它指示清单中只列出产生目标 代码的宏展开;
.lall 列出包括注释在内的所有宏展开;
.sall 则不列出任何信息;
宏库的建立与调用:
如果程序中定义了很多宏,可以把这些宏组合起来建立一个独立的文件,这个只包含若干个宏定义的文件称为宏库。扩展名是mac 或inc来表示。当需要使用宏库中的某些宏定义时,只需要在该程序的开始用INCLUDE语句说明
INCLUDE C:\MACRO.MAC
伪指令PURGE:
宏汇编程序提供了伪操作PURGE,用来在适当的时候取消宏定义。
PURGE伪指令的一般格式是:
PURGE 宏定义名[,…]
方括号表示PURGE可以取消多个宏定义,宏名之间用逗号隔开。如宏定义:
SUB MACRO VARX,VARY,RESULT
┇
ENDM
宏调用:SUB X,Y,Z
PURGE SUB