The power of a macro can be increased by the use of optional parameters. The parameters allow variable values to be declared when the macro is called. For example, the parameter version of IND1 is LOAD, which can be used to load memory utilizing various addressing modes:
When parameters are included in a macro call, the following rules apply to the parameter list:
One comma and/or one or more blanks delimit parameters.
A semicolon terminates the parameter list and starts the comment field.
Single quotes (') may be included as part of a parameter except as the first character.
A parameter may be enclosed in single quotation marks ('), in which case the quotes are removed and the string is used as the parameter. This function allows blanks, commas, or semicolons to be included in the parameter. To include a quotation mark in a quoted parameter, include two quotation marks ('').
Missing or null parameters are treated as strings of zero length.
The macro operator @ references the parameter list in the macro call. When used in an expression, it is replaced by the number of parameters in the macro call. For example, the following .if directive causes the conditional code to be expanded if there are more than ten parameters in the macro call:
When used with a constant or symbol (not a macro definition parameter), the @ operator references the individual parameters in the parameter list. The following example demonstrates how this function may define and call a macro to establish a program memory table:.macro X .word @1,@2,@3 ; first, second, third arguments .word @Q ; Qth argument .endm macro call Assembled Program Q=3 Q=3 . . X 3,4,5 X 3,4,5 . .WORD 3,4,5 ; first, second, third arguments . .WORD 5 ; Qth argument
This technique eliminates the need for naming each parameter in the macro definition, which is particularly useful to deal with long parameter lists. With the @ parameter count operator, it is possible to create macros that have a variable number of parameters.
Note: The @ operator is replaced during macro expansion in comments; ordinary macro parameters are not.
Note: A .doparm loop acts as a macro, and the above description of the @ operator also applies.
The "^" macro operator is used for concatenation. The "^" is removed and the strings on each side of the operator are compressed together after parameter substitution. If the right string is a defined absolute null symbol (not a macro definition parameter), the decimal value of the symbol is used; if "^^" is used, the hex value of the symbol is used.
.macro LABEL,X R^X: .word X ; X is macro parameter R^Q: .word Q ; Q is defined symbol R^^Q: .word Q .endm Macro call Generated code(without comments) Q=11 Q=11 . . LABEL 0 LABEL 0 . R0: .word 0 . R11: .word Q R0x000B: .word Q
When a label is defined within a macro, a duplicate definition results from the second and each subsequent call of the macro. This problem can be avoided by using the .MLOC directive to declare labels local to the macro definition. The .MLOC directive may occur at any point in a macro definition, but it must precede the first occurrence of the symbol(s) it declares local. Any symbol used before the .MLOC will not be recognized as local. Local macro labels (symbols) appear as ZZdddd, where dddd is a particular decimal number.
; BLOCK MOVE ; SOURCE is source, DEST is destination, ; DESTEND is last dest addr .macro MOVE,SOURCE,DEST,DESTEND ld X,#SOURCE ld B,#DEST .mloc BMV BMV: ld A,[X+] x A,[B+] ifbne #DESTEND+1 jmp BMV .endm Source Program Generated Code . . MOVE 4000,40,47 MOVE 4000,40,47 . ld X,#4000 . ld B,#40 . ZZ0000: . ld A,[X+] . x A,[B+] . ifbne #47+1 . jmp ZZ0000 . . MOVE 5000,50,57 MOVE 5000,50,57 . ld X,#5000 . ld B,#50 . ZZ0001: . ld A,[X+] . x A,[B+] . ifbne #57+1 . jmp ZZ0001
The conditional assembly directives allow the user to generate different lines of code from the same macro simply by varying the parameter values used in the macro calls. These directives are described in Reference I, Assembly Directives.
The following examples show the use of the .do, .enddo, and .exit directives. The macro CTAB generates a constant table from 0 to MAX where MAX is a parameter of the macro call. Each word has DY: label, where Y is the decimal value of the data word:
Nested macro calls are allowed; that is, a macro definition may contain a call to another macro. When a macro call is encountered during macro expansion, the state of the macro currently being expanded is saved and expansion begins on the nested macro. Upon completing expansion of the nested macro, expansion of the original macro resumes. The allowed number of levels of nesting depends on the sizes of the parameter lists, but at least ten is typical.
A logical extension of a nested macro call is a recursive macro call; that is, a macro that calls itself. This is allowed, but care must be taken not to generate an infinite loop.
A macro definition can be nested within another macro. Such a macro is not defined until the outer macro is expanded and the nested .macro statement is executed. This allows the creation of special-purpose macros based on the outer macro parameters and, when used with the .mdel directive, allows a macro to be defined only within the range of the macro that uses it.
Normally all lines within a macro definition are stored with the macro. However, any text following ";;" is removed before being stored. A line that starts with ";;" is completely removed from the macro definition. These lines appear on the listing of the macro definition; they do not appear on an expansion.