.macro 和.endm 用来定义汇编宏
例如下面的例子定义了一个关于整形数累加的sum宏:
.macro sum from=0, to=5
.long \from
.if \to-\from
sum "(\from+1)",\to
.endif
.endm
如上定义 ’SUM 0,5‘展开后相当于:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.macro macname ¶
.macro macname macargs … ¶
宏定义以macname开头。如果宏定义需要参数,在宏名称后面指定他们的参数名,以“,”或空格分割。可以限定对应参数必须为非空(参数后面添加':req'),或者限定对应参数引用后面剩余的所有参数(参数后面添加':vararg')。如需为宏参数提供默认值则在参数后面附带‘=deflt’。我们不能定义两个同名的宏,除非使用.purgem(查看.purgen)在两个宏之间约束。下面的是一些有效的.macro声明:
.macro comm
宏名为 comm 的定义,它没有参数
.macro plus1 p, p1
.macro plus1 p p1
两个声明plus1的宏,它有两个参数,宏定义里面,用‘\p’或 ‘\p1’来进行参数计算
.macro reserve_str p1=0 p2
名为reserve_str的宏定义有两个参数。第一个参数有一个默认值,第二个没有。宏定义之后,可用‘reserve_str a,b’调用宏(用a替换‘\p1’计算,用b替换‘\p2’参与计算)或者用‘reserve_str ,b’ 调用宏(替换‘\p1’为默认参数0,‘\p2’替换为b)
.macro m p1:req, p2=0, p3:vararg
宏名为m,至少需要三个参数,第一个参数制定参数非空,但是第二参数使用默认参数,第三个参数引用调用时传递的剩下所有参数
当调用一个宏时,可以按照参数位置直接给出参数的值,也可以使用参数名制定。例如:'sum 9, 17'或'sum to=17, from=9'
🚩 注意,每个macargs 可以是任何目标架构允许的字符,如果对应目标架构特定的字符有特殊含义,当他们用来定义宏参数就会有一定的问题。例如,冒号可以用来作为符号名称,但是在体系架构的特定代码中冒号作为符号的结束(label标签),而宏参数替换并不知道这个标签将包含冒号的整个标识符为一个标识符,仅仅检查并替换其他标识符的对象。这种宏定义如下:
.macro label l
\l:
.endm
以上代码可能不能正常运行,调用’label foo‘不会创建 'foo' 的lalel,而将文本‘\l:’插入为汇编代码,最终可能生成一个不能识别的标识符错误
同样的问题可能发生在结束字符’.‘,它长被允许作为操作码的名字(也可以是标识符名称)。例如构造一个创建操作符的宏,用base和length作为参数:
.macro opcode base length
\base.\length
.endm
用 ‘opcode store l来调用将不会创建一个 ‘store.l’指令而相反编译器尝试解析文本‘\base.\length’最后出错。
这有几个可能这类问题的相关错误:
Insert white space
如果参数可能包含空格则最简单的办法,如:
.macro label l
\l :
.endm
使用‘\()’
字符串 ‘\()’可以用来分割下面文本中宏参数的结束,如:
.macro opcode base length
\base\().\length
.endm
使用 alternate的宏语法格式
使用alternate 语法宏与(&)符号可以用来作为分割器,如:
.altmacro
.macro label l
l&:
.endm
🚩 注意:这种安全标识字符串参数的伪操作也适用于.irp(.irp symbol,values…)和.irpc(.irpc symbol,values…)的标识符。
另一个问题在宏调用传递实际参数过程中发生:多个参数用空格和逗号来分割。对于参数本身包含空格和逗号(或潜在其他非阿拉伯数字或字母的字符)单独的参数需要括号()或中括号[]或双引号"括起来。
由于只有双引号在建立参数的时候才会去掉,因此在特定的情况下只能用双引号,当处理这样包含引号参数的字符串的时候需要特别注意两个转义模式:其一是两个相邻双引号会在结果参数里被转义一个双引号,单行括起来的引号也会被剔除。但是双引号也可以通过反斜杠\转义,但这个反斜杠在扩展宏中不会保留在实际的参数中而是被识别为/。
考虑上面第一种转义机制的结果,两个字符串文本的分割需要用空格(或者最好用逗号)。换一种说法,像这种相邻的字符串文本-即使用-已经隔开他们在宏参数识别时也不会识别为连接,即使用空格分开。
这个不用于其他伪操作,如:. .ascii.
.endm
标记宏定义的结束
.exitm
提前从当前宏定义退出
\@
as 维护了在这个伪变量中有多少个宏的计数;可以通过‘\@’拷贝出对应的数字,这个只能用在宏定义里
LOCAL name [ , … ]
警告:LOCAL 仅在通过关键字--alternate’ or .altmacro. 选用“alternate macro syntax”模式下才有效,详见: .altmacro.