Assembler Commands - Macro

A macro is a user declared sequence of instructions. When a macro is invoked the code contained in the macro is inserted into the program in place of the macro invocation. Unlike a subroutine, a macro does not exist as code until it is invoked and then the code is inserted into the program. Each macro must be defined by a unique name. Once a macro is defined the code that it contains may be inserted into a program by using the macro name in the assembly source in the same way an instruction or opcode would be used. The macro definition should appear in the code before it is invoked. Calling macros that are defined later in the code may result in an error if the macro call is between a branching instruction and its destination label. The error message:
ERROR: Address or value of symbol has changed during assembly.
See 'Help' on Macros for possible causes
will be displayed if such an error occurs. Placing the macro definitions at the top of the code will prevent macro calls from causing this error.

Macros are defined using the syntax:

macName MACRO
code
ENDM

Up to thirty-six parameters may be used in the macro as \0 through \9 and \A through \Z. The parameters are specified when the macro is invoked. The assembler replaces the macro argument \n with the parameter specified. Parameter \0 always refers to the .size code letter (B or W or L). Use angle brackets to enclose arguments that contain white space <this is one argument>. See MACRO.X68 in the examples folder for an example.

Example:

OPT MEX
* Convert the ASCII character in \1 to upper case
toUpper MACRO
IFNC \0,B ;if .B not specified
FAIL ERROR: toUpper is .B only
MEXIT ;exit macro
ENDC
CMP.B #'a',\1
BLO NOT\@ ;if not lower case
CMP.B #'z',\1
BHI NOT\@ ;if not lower case
SUB.B #$20,\1 ;convert to upper case
NOT\@
ENDM
START ORG $1000
MOVE.B #'a',D0
toUpper.B D0 ;invoke toUpper macro, D0 is parameter \1
MOVE.B #9,D0
TRAP #15 ;Halt Simulator
END START

Labels Within Macros
The \@ directive creates a unique label. The \@ directive should be used to create labels in macros to avoid having multiple definitions of the same label when a macro is invoked more than once. The \@ directive may be used in conjunction with other text to create a descriptive label. The assembler will replace \@ with a string of the form _n, where n is a unique decimal number.
References to an assembler-generated label always refer to the label of the given form defined in the current level of macro expansion. Such a label is referenced as an operand by specifying the same character string as that which defines the label.

The MEXIT directive

The directive MEXIT may be used to exit macro processing. All remaining statements in the macro are skipped up to the ENDM directive.

The NARG directive

NARG is a special symbol when referenced within a macro expansion. The value assigned to NARG is the index of the last argument passed to the macro in the parameter list (even if nulls). NARG is a reserved word inside a macro but is undefined outside of macro expansion, and may be referenced as a user-defined symbol.
In the following example the NARG directive is used to check for the presence of two arguments. If the macro is called with fewer or more than two arguments an error is created by using the FAIL directive and the macro is exited with MEXIT:

MAC MACRO
IFNE NARG-2 ;if not 2 arguments
FAIL ERROR, MAC requires 2 arguments
MEXIT
ENDC
MOVE.\0 \1,D0
CLR.L \2
ENDM
OPT MEX
START ORG $1000
MAC #'A' ;causes error 'ERROR, MAC REQUIRES 2 ARGUMENTS'
MAC #1,D0
MOVE.B #9,D0
TRAP #15 ;Halt Simulator
END START

Null arguments and Conditional Assembly in Macros

The conditional assembly directive IFxx may be used to test for missing (null) parameters. To assemble conditionally if parameter 1 is null, either of the following directives would be correct:

IFC '','\1'
or
IFC '\1',''

To assemble conditionally if a parameter is present would use either of the IFNC formats analogous to the above two.
The condition IFARG may also be used to check for the presence of an argument in a macro call. The syntax is:

IFARG n
<statements>
ENDC

Where n specifies the argument (0 - 9, A - Z). If the specified argument is not present in the macro call the enclosed statements are not included in the program.

It is possible to specify a null argument in a macro call by an empty string (not a blank) ' ' or empty angle brackets <>. The following listing is a portion of an .L68 file created by EASy68K. Line 7 contains the assembler option MEX to expand macros in the listing file. The macro is named foo and is defined in lines 8 through 14. Line 9 in the macro is using the conditional assembly directive IFC to check for the presence of argument 2. Lines 17m through 36m are macro calls and the expanded macro statements as indicated by the lower case m following the line number. If nested macro calls are made multiple m's are displayed. The macro foo is called on line 17m with 3 arguments. Line 18m shows the result of comparing argument 2 with ' ' was FALSE. Since the result of the IFC conditional statement was false the NOP instruction on line 10 of the macro was not assembled. On line 23m angle brackets <> are used to specify argument 2 is null. Line 24m shows the result of the IFC statement is TRUE and line 25m shows the NOP instruction has been assembled as a result. The same is true on line 30m where an empty string ' ' is used for argument 2.

7 OPT MEX
8 foo MACRO
9 IFC '\2',''
10 nop
11 ENDC
12 move #\1,d0
13 move #\3,d1
14 ENDM
15
16 START
17m foo 1,2,3 no null argument
FALSE 18m IFC '2',''
19m ENDC
303C 0001 20m MOVE #1,D0
323C 0003 21m MOVE #3,D1
22m ENDM
23m foo 4,<>,6 argument 2 is null
TRUE 24m IFC '',''
4E71 25m NOP
26m ENDC
303C 0001 27m MOVE #4,D0
323C 0003 28m MOVE #6,D1
29m ENDM
30m foo 7,'',9 argument 2 is null
TRUE 31m IFC '',''
4E71 32m NOP
33m ENDC
303C 0001 34m MOVE #7,D0
323C 0003 35m MOVE #9,D1
36m ENDM
37
103C 0009 38 MOVE.B #9,D0
4E4F 39 TRAP #15 Halt Simulator
40
41 END START

Refer to the Examples folder for additional sample code.