三、宏指令的使用
3.宏调用的参数个数可以与定义时不一致。
宏调用时使用的实参个数应该与宏定义时形参个数一致。但汇编程序并不要求它们必须一致。
若实参个数多于形参个数,则多余的实参被忽略
若实参个数少于形参个数,则多余的形参用 空 来代替。
4.特殊的宏运算符
(1) 强迫替换运算符 &
在宏定义中,若参数在其它字符的紧前或紧后,或者参数出现在带引号的字符串中时,就必须使用该运算符,以区分参数
例:
下面定义的宏指令JUMP中,参数CON作为操作码的一部分
JUMP MACRO CON, LIB
J&CON LAB
ENDM
调用宏JUMP及其扩展如下:
JUMP NZ HERE
+ JNZ HERE
JUMP Z THERE
+ JZ THERE
例2:
下而定义的宏MSGGEN中,两个参数合并成标号,一个参数用在字符串中
MSGGEN MACRO LAB, NUM, XYZ
LAB&NUM DB 'HELLO MR&XYZ', 0DH, 0AH, 24H
ENDM
调用宏MSGGEN及其宏扩展如下:
MSGGEN MSG, 1, TAYLOR
+ MSG1 DB 'HELLO MRTAYLOR', 0DH, 0AH, 24H
(2) 字符串读运算符 <>
在宏调用,重复块和条件汇编中,由它括起的内容作为一个字符串。
在宏调用时,若实参包含逗号,空格等间隔符,则必须使用读运算符,以保证实参的完整。
若实参是某个有特殊意义的字符,为了使它只表示字符本身,也要使用该运算符把它括起来。
例:
定义如下宏
DFMESS MACRO MESS
DB '&MESS', 0DH, 0AH, 0
ENDM
调用及其扩展如下:
DFMESS <THIS IS A EXAMPLE>
+ DB 'THIS IS A EXAMPLE', 0DH, 0AH, 0
DFMESS THIS IS A EXAMPLE
+ DB 'THIS', 0DH, 0AH, 0
(3) 文字字符运算符 !
该运算符使用其后的一个字符只作为一般字符。
在宏调用时,如果实参中含有一些特殊字符,为了使这些特殊字符作为一般字符来处理,那么就必须在其前使用该运算符。
例: 调用上例DFMESS
DFMESS <CAN NOT CMTC !> 09>
+ DFMESS 'CAN NOT CMTC > 09', 0DH, 0AH, 0
DFMESS <CAN NOT CMTC > 09>
+ DFMESS 'CAN NOT CMTC ', 0DH, 0AH, 0
(4) 表达式运算符 %
在宏调用时,使用该运算符把其后表达式结果作为实参替换,而非表达式本身
例: 调用上例DFMESS
DFMESS %(12+3-4)
+ DB '11', 0DH, 0AH, 0
DFMESS 12+3-4
+ DB '12+3-4', 0DH, 0AH, 0
(5) 宏注释 ;;
在宏定义中,如果注释以两个分号引导,那么宏展开时,该注释不出现。
5. 宏与子程序的区别
(1) 宏调用是通过宏指令名进行的,在汇编时,由汇编程序把宏展开, 有多少次宏调用,就有多少次宏展开。因此并不简化子程序。
子程序调用是在执行期执行CALL指令进行的,子程序代码只在目标程序中出现一次,所以目标程序也得到相应的优化。
(2) 宏调用时参数由汇编程序通过实参替换的方式传递,所以参数很灵活。
子程序调用时参数通过寄存器,堆栈或约定存储单元传递。
(3) 宏调用时在汇编时完成的,所以不需要额外的时间开销。
子程序调用和子程序返回均需要时间,而且还涉及堆栈。