If an actual argument is a string containing characters that
the assembler interprets as separators (such as a tab, space,
or comma), the string must be enclosed by delimiters. String
delimiters for macro arguments are usually paired angle brackets
(<>). A quoted literal enclosed in double quotes ("") is also a
valid string argument.
The assembler also interprets any character
(except A, B, C, D, O, or X) after an initial circumflex (^)
as a delimiter. Note that ^B, ^D, ^O, and ^X are used as radix
control operators rather than argument delimiters. ^A is used
as the ASCII operator and ^C is used as the complement operator.
To pass an angle bracket as part of a string, you can use the
circumflex form of the delimiter.
The following are examples of delimited macro arguments:
<HAVE THE SUPPLIES RUN OUT?>
<LAB: CLR R4>
"A quoted literal is taken as a single parameter value."
^%ARGUMENT IS <LAST,FIRST> FOR CALL%
^?EXPRESSION IS <5+3>*<4+2>?
In the last two examples, the initial circumflex indicates
that the percent sign (%) and question mark (?) are the
delimiters. Note that only the left-hand delimiter is preceded
by a circumflex.
The assembler interprets a string argument enclosed by delimiters
as one actual argument and associates it with one formal
argument. If a string argument that contains separator characters
is not enclosed by delimiters, the assembler interprets it as
successive actual arguments and associates it with successive
formal arguments.
For example, the following macro definition has one formal
argument:
.MACRO DOUBLE_ASCII STRNG
.ASCII "STRNG"
.ASCII "STRNG"
.ENDM DOUBLE_ASCII
The following two macro calls demonstrate actual arguments with
and without delimiters:
DOUBLE_ASCII <A B C D E>
.ASCII "A B C D E"
.ASCII "A B C D E"
DOUBLE_ASCII A B C D E
%MACRO64-E-TOOMNYARGS, Too many arguments in macro call
Note that the assembler interprets the second macro call as
having five actual arguments instead of one actual argument with
spaces.
When a macro is called, the assembler removes normal delimiters
around a string before associating it with the formal arguments.
However, a quoted literal within double quotes is treated as a
single token and retains its double quote delimiters.
If a string contains a semicolon (;), the string must be
enclosed by delimiters; otherwise, the semicolon will mark the
start of the comment field. Further, if the string contains a
semicolon, you cannot continue the line unless the string is a
quoted literal.
You can nest macro invocations, that is, a macro definition can
contain a call to another macro. If, within a macro definition,
another macro is called and is passed a string argument, you must
delimit the argument so that the entire string is passed to the
second macro as one argument.
The following macro definition contains a call to the DOUBLE_
ASCII macro defined earlier:
.MACRO CNTDA LAB1,LAB2,STR_ARG
LAB1: .BYTE LAB2-LAB1-1 ; Length of 2*string
DOUBLE_ASCII <STR_ARG>
; Call DOUBLE_ASCII macro
LAB2:
.ENDM CNTDA
Note that the argument in the call to DOUBLE_ASCII is enclosed in
angle brackets even though it does not contain any separator
characters. The argument is thus delimited because it is a
formal argument in the definition of the macro CNTDA and will
be replaced with an actual argument that may contain separator
characters.
The following example calls the macro CNTDA, which in turn calls
the macro DOUBLE_ASCII:
CNTDA ST,FIN,<LEARN YOUR ABC'S>
ST: .BYTE FIN-ST-1
DOUBLE_ASCII <LEARN YOUR ABC'S>
.ASCII "LEARN YOUR ABC'S"
.ASCII "LEARN YOUR ABC'S"
FIN:
In addition to nested macro invocations, you can
also nest macro definitions. That is, you can define
one macro within another. In this example, the
INNER_MACRO_DEF macro is not defined until the OUTER_MACRO_DEF
macro is invoked and expanded:
.macro OUTER_MACRO_DEF
.macro INNER_MACRO_DEF
...
.endm INNER_MACRO_DEF
.endm OUTER_MACRO_DEF
You can use this capability to define a macro that redefines
itself:
.macro SETUP
A = 75
B = 92
C = 87
D = 0
E = -12
F = 42
.macro SETUP
; Setup is done - do nothing
.endm SETUP
.endm SETUP
In this example, the SETUP macro defines a number of assembly
constants. After the SETUP macro has been expanded once, its
work is done. Subsequent expansions of the setup macro need not
take any action. Therefore, the SETUP macro redefines itself
to a macro whose expansion includes only a comment statement.
As described elsewhere, when you redefine a macro, the original
version of the macro is automatically deleted. If that macro is
currently expanding (as would be the case with the previous SETUP
macro), the new definition is immediately associated with the
macro name. However, the old definition is retained until all
pending expansions complete normally. When all pending expansions
complete, the old version of the macro is deleted. Thus, the
SETUP macro may be invoked any number of times in the assembly
unit. Since the first expansion redefines itself, the expansion
of the SETUP macro has no effect other than the first time it is
invoked.
Another way to pass string arguments in nested macros is to
enclose the macro argument in nested delimiters.
NOTE
Each time you use the delimited argument in a macro call,
the assembler removes the outermost pair of delimiters
before associating it with the formal argument. This method
is not recommended because it requires that you know how
deeply a macro is nested.
The following macro definition also contains a call to the
DOUBLE_ASCII macro:
.MACRO CNTDA2 LAB1,LAB2,STR_ARG
LAB1: .BYTE LAB2-LAB1-1 ; Length of 2*string
DOUBLE_ASCII STR_ARG ; Call DOUBLE_ASCII macro
LAB2:
.ENDM CNTDA2
Note that the argument in the call to DOUBLE_ASCII is not
enclosed in angle brackets.
The following example calls the macro CNTDA2:
CNTDA2 BEG,TERM,<<MIND YOUR P'S AND Q'S>>
BEG: .BYTE TERM-BEG-1 ; Length of 2*string
DOUBLE_ASCII <MIND YOUR P'S AND Q'S>
; Call DOUBLE_ASCII macro
.ASCII "MIND YOUR P'S AND Q'S"
.ASCII "MIND YOUR P'S AND Q'S"
TERM:
Note that even though the call to DOUBLE_ASCII in the macro
definition is not enclosed in delimiters, the call in the
expansion is enclosed because the call to CNTDA2 contains nested
delimiters around the string argument.