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.