14.1.4 Macros:

There are two forms of macros supported by CEF: #DEFINE and .MACRO. They perform the same basic function, but there are significant differences. The .MACRO directive defines a multi-line macro, which is ended with the .ENDM directive. The #DEFINE directive defines a single-line macro. A “macro reference” is simply the name of a previously-defined macro. A Macro definition may contain one or more formal arguments. Arguments are optional in any macro, but if present they must be delimited by whitespace in .MACRO and paired parentheses in #DEFINE. Format:

.MACRO name {argument1{,argument2{...}}}





#DEFINE name {(argument1{,argument2{...}})}

Macro names can include any non-whitespace character - which allows macros to look like CPU instructions or even new directives. Macros are always checked before directives are processed, and before assembly is passed to the CPU assembler. Macros allow a single line in the source file to insert an arbitrarily long sequence of source lines into the source. This is properly called an in-line expansion. The assembler replaces the line containing the macro reference with the contents of the macro. It replaces any occurrence of formal arguments in the macro with the actual arguments specified on the macro line. This is called argument substitution. The .MACRO form substitutes based on tokens, whereas #DEFINE substitutes based on literal text.

Macros have two types of arguments: actual and formal. Actual arguments are the string literal values that follow the name of the macro on the line that references the macro name. Formal arguments are those that are specified in the definition of the macro. Formal and actual arguments have a strict positional relationship. In other words, the first actual argument replaces all occurrences of the first formal argument in the macro definition. The second actual argument replaces the second formal argument, and so forth. The number of actual arguments must be equal to, or less than, the number of formal arguments. If there are more actual arguments than formal arguments, the assembler reports an error. Both actual and formal arguments are separated with commas. .MACRO arguments are case-insensitive while #DEFINE arguments are case-sensitive.

Note that string literals for actual parameters can contain commas as part of the literal if the string is delimited by single (') or double (") quotes. However, the quotes will be part of the string literal during argument substitution.

Default values can be specified in the macro definition. If no corresponding actual argument is supplied, the default value specified for the formal argument is used as the actual argument. Default values have the format:

formal_argument_name = default_value

For example:

.MACRO REC ARG1=0,ARG2=128,ARG3=255





#DEFINE REC1(x=0,y=128,z=255) .BYTE x \ .BYTE y \ .LONG z

Assuming the above macro definitions, the following line:

REC 1,2

would be expanded as:



.LONG 255

A call to


would expand to the same code.

Actual arguments are substituted literally unless the argument is a symbol name preceded by a backslash (\), in which case the numeric value of the symbol is used instead. Example:

REC \A,2

Arguments can be concatenated within the .MACRO form of macro by enclosing the formal argument within single quotes ('). Normally argument substitution is only done when the formal argument is found as a separate token in the macro definition. The apostrophes must delimit the text in the macro. Note that the apostrophes themselves do not appear in the macro expansion. For instance, if ARG1 is a format argument and TEST is used as the corresponding actual argument, then ABC'ARG1' in the macro block will be expanded to ABCTEST. Example of concatenation:




Labels can be used in macro blocks, however if the macro with labels is expanded more than once, duplicate label symbol errors will occur. Macros can create unique labels if the label is specified as a formal parameter preceded by a question mark (?). Created unique labels range from 30000$ to 65535$. Each time a created unique label is required, the numeric part is incremented by 1. If the formal argument has a matching actual argument, that argument is used. Otherwise a label is created. Example of definition:




The following shows two calls and the macro expansions for those calls, based on the foregoing definition:


30000$: .BYTE 12

CHOOSE 32,10$

10$: .BYTE 32

Macros can be deleted with .MDELETE. They can also be nested. That is, a macro definition can contain a reference to another macro - even itself. However, one should be careful to avoid infinite recursion. The expansion of macros within macros only happens when the outer macro is expanded and the internal macro reference is assembled.

The following table compares the two forms of macros:



Arguments delimited by



Arguments case-sensitive?







By token

By literal text


CEF master assemblers support the following arithmetic operators in places where expressions are allowed. Note that conforming implementations may provide supersets of this functionality.






Subtraction or unary minus








Parentheses for evaluation ordering.