.macro
The commands .macro
and .endm
allow you to define macros that
generate assembly output. For example, this definition specifies a macro
sum
that puts a sequence of numbers into memory:
.macro sum from=0, to=5 .long \from .if \to-\from sum "(\from+1)",\to .endif .endm
With that definition, ‘SUM 0,5’ is equivalent to this assembly input:
.long 0 .long 1 .long 2 .long 3 .long 4 .long 5
.macro macname
¶.macro macname macargs …
¶Begin the definition of a macro called macname. If your macro
definition requires arguments, specify their names after the macro name,
separated by commas or spaces. You can qualify the macro argument to
indicate whether all invocations must specify a non-blank value (through
‘:req
’), or whether it takes all of the remaining arguments
(through ‘:vararg
’). You can supply a default value for any
macro argument by following the name with ‘=deflt’. You
cannot define two macros with the same macname unless it has been
subject to the .purgem
directive (see .purgem name
) between the two
definitions. For example, these are all valid .macro
statements:
.macro comm
Begin the definition of a macro called comm
, which takes no
arguments.
.macro plus1 p, p1
.macro plus1 p p1
Either statement begins the definition of a macro called plus1
,
which takes two arguments; within the macro definition, write
‘\p’ or ‘\p1’ to evaluate the arguments.
.macro reserve_str p1=0 p2
Begin the definition of a macro called reserve_str
, with two
arguments. The first argument has a default value, but not the second.
After the definition is complete, you can call the macro either as
‘reserve_str a,b’ (with ‘\p1’ evaluating to
a and ‘\p2’ evaluating to b), or as ‘reserve_str
,b’ (with ‘\p1’ evaluating as the default, in this case
‘0’, and ‘\p2’ evaluating to b).
.macro m p1:req, p2=0, p3:vararg
Begin the definition of a macro called m
, with at least three
arguments. The first argument must always have a value specified, but
not the second, which instead has a default value. The third formal
will get assigned all remaining arguments specified at invocation time.
When you call a macro, you can specify the argument values either by position, or by keyword. For example, ‘sum 9,17’ is equivalent to ‘sum to=17, from=9’. You can also omit values when using keywords, so for example ‘sum to=6’ is equivalent to ‘sum 0, 6’.
Note however that when operating in altmacro mode arguments can only be
specified by position, not keyword. See .altmacro
.
Thus for example:
.macro foo bar=1, baz=2 .print "\bar \baz" .endm foo baz=3 .altmacro foo baz=3
Will print:
1 3 baz=3 2
Note that since each of the macargs can be an identifier exactly
as any other one permitted by the target architecture, there may be
occasional problems if the target hand-crafts special meanings to certain
characters when they occur in a special position. For example, if the colon
(:
) is generally permitted to be part of a symbol name, but the
architecture specific code special-cases it when occurring as the final
character of a symbol (to denote a label), then the macro parameter
replacement code will have no way of knowing that and consider the whole
construct (including the colon) an identifier, and check only this
identifier for being the subject to parameter substitution. So for example
this macro definition:
.macro label l \l: .endm
might not work as expected. Invoking ‘label foo’ might not create a label called ‘foo’ but instead just insert the text ‘\l:’ into the assembler source, probably generating an error about an unrecognised identifier.
Similarly problems might occur with the period character (‘.’) which is often allowed inside opcode names (and hence identifier names). So for example constructing a macro to build an opcode from a base name and a length specifier like this:
.macro opcode base length \base.\length .endm
and invoking it as ‘opcode store l’ will not create a ‘store.l’ instruction but instead generate some kind of error as the assembler tries to interpret the text ‘\base.\length’.
There are several possible ways around this problem:
Insert white space
If it is possible to use white space characters then this is the simplest solution. eg:
.macro label l \l : .endm
Use ‘\()’
The string ‘\()’ can be used to separate the end of a macro argument from the following text. eg:
.macro opcode base length \base\().\length .endm
Use the alternate macro syntax mode
In the alternative macro syntax mode the ampersand character (‘&’) can be used as a separator. eg:
.altmacro .macro label l l&: .endm
Note: this problem of correctly identifying string parameters to pseudo ops
also applies to the identifiers used in .irp
(see .irp symbol,value
…)
and .irpc
(see .irpc symbol,values
…) as well.
Another issue can occur with the actual arguments passed during macro
invocation: Multiple arguments can be separated by blanks or commas. To have
arguments actually contain blanks or commas (or potentially other non-alpha-
numeric characters), individual arguments will need to be enclosed in either
parentheses ()
, square brackets []
, or double quote "
characters. The latter may be the only viable option in certain situations,
as only double quotes are actually stripped while establishing arguments. It
may be important to be aware of two escaping models used when processing such
quoted argument strings: For one two adjacent double quotes represent a single
double quote in the resulting argument, going along the lines of the stripping
of the enclosing quotes. But then double quotes can also be escaped by a
backslash \
, but this backslash will not be retained in the resulting
actual argument as then seen / used while expanding the macro.
As a consequence to the first of these escaping mechanisms two string literals
intended to be representing separate macro arguments need to be separated by
white space (or, better yet, by a comma). To state it differently, such
adjacent string literals - even if separated only by a blank - will not be
concatenated when determining macro arguments, even if they’re only separated
by white space. This is unlike certain other pseudo ops, e.g. .ascii
.
.endm
¶Mark the end of a macro definition.
.exitm
¶Exit early from the current macro definition.
\@
¶as
maintains a counter of how many macros it has
executed in this pseudo-variable; you can copy that number to your
output with ‘\@’, but only within a macro definition.
\+
¶Similar to the \@
pseudo-variable, as
also maintains
a per-macro count of the number of times that that macro has been executed.
You can copy that number to your output with ‘\+’, but
only within a macro definition.
LOCAL name [ , … ]
¶Warning: LOCAL
is only available if you select “alternate
macro syntax” with ‘--alternate’ or .altmacro
.
See .altmacro
.