参数对于函数的重要性不言而喻,对于宏的参数如下定义。
name MACRO parameterlist
statements
ENDM
简单情况下,对于parameterlist就是参数名字用,号格开,比如:
clear_reg MACRO reg
xor reg, reg
ENDM
调用的时候,用这种格式:
clear_reg eax
对于宏过程,这个是唯一的调用格式。
参数的传递和执行期的函数的参数传递也是很不一样的。参数是被直接替换的。你可以作这么一个试验:
TestMacro MACRO param
echo param
%echo param
ENDM
TextVar TEXTEQU <Hello>
TestMacro TextVar
输出的结果是TextVar和Hello。到底是怎么回事就不用我多说了。你甚至可以进一步测试:
TestMacro MACRO param
param TEXTEQU <How are you>
ENDM
TextVar TEXTEQU <Hello>
TestMacro TextVar
%echo TextVar
输出的结果是How are you。可见所谓的参数不过就是替换。参数名会被引数名给替换(引数就是调用时候传递过去的那些参数)。由于MASM中宏这个系统中,所有的这些变量名的符号都是在一个共同的空间之中(呵呵,怎么听起来像数学术语?),都是全局的东西。
对于参数可以进行一些限定修饰,比如让你调用的时候一定要传递这个参数:
Clear_reg MACRO reg:REQ
xor reg, reg
ENDM
或者指定一个缺省值:
Clear_reg MACRO reg:=<eax>
xor reg, reg
ENDM
或者让参数个数成为一个变数。
Clear_reg MACRO regs:VARARG
FOR reg, <regs>
xor reg, reg
ENDM
ENDM
不过要注意的是VARARG修饰的参数必须是参数中的最后一个。
宏过程和宏函数的区别在于是否有返回值。当然这里的返回值和执行期的函数的返回值也是很不一样的。执行期的函数是通过eax来传递返回值的。而这里,也不过是直接替换而已。返回值的语法是这样的:
EXITM textitem
一个宏函数可以有多个EXITM,就像C中的函数可以有多个return一样。不过必须返回值一致。看一个简单的例子
Who MACRO
EXITM <taowen>
ENDM
%echo Who()
结果是显示taowen。如果把()去掉,则显示的是who。可见对于宏函数的调用一定要加上 ()。而调用宏过程则不能加()。看一个有趣的例子:
Who MACRO temp
%echo temp
ENDM
Who()
显示的结果是()。说明()被当作传递给宏过程的参数了。
可以比较随意的使用返回值,可以把返回值这么用。
Who MACRO
EXITM <taowen>
ENDM
Who() TEXTEQU <genius>
这样就定义了汇编期文本变量,值为genius。可见宏函数可以用在任何文本变量可以出现的地方,很多地方可以把高级语言中函数中那些类推过来。
宏中可以有局部变量,它看起来像局部的,实际上不过是一些名称上的小技巧。
对于局部变量有两点事实:1、在函数外无法访问,2、在对函数的不同次的调用中其值应该不受前次调用的影响。
TestMacro MACRO
LOCAL LocalVar
%echo LocalVar
LocalVar TEXTEQU <Hello>
ENDM
如果对于函数的调用每次之间会互相影响,那么这么调用:
TestMacro
TestMacro
第一次会产生一个未定义变量的错误,而第二次就会输出Hello。事实上,由于LocalVar 是LOCAL的。所以两次都是未定义错误。这个就体现了局部变量的多次调用的独立性。
下面我们来揭穿局部变量的底牌。不用我多叙述,直接看看这个你就明白了:
TestMacro MACRO
LOCAL LocalVar
echo LocalVar
ENDM
TestMacro
TestMacro
输出的结果是:??0000与??0001。这个就是局部变量的实际名字。局部变量就是通过怪怪的名字让外部无法访问(你不知道它是什么名字),然后在每次展开同一个宏的时候用不同的名字替换局部变量的名字,使得多次调用之间不会互相影响。
其实你可以试验一下这个:
??0000