Macro language

The .macro directive allows you to generate new commands that can create assembler output. A simple example follows:

foo           .macro  a, b
              .byte   \a
              .word   \b - 1
              .long   0
              .endm

This creates a new macro named foo which takes two arguments a and b. To use an argument inside the macro, prefix the parameter name with a backslash \.

Rules for argument substitutions

When looking for argument substitutions, the longest match is favored. This means if you have parameters called a and aa, substituting the longer name is always tried before shorter names, ignoring the order the parameters are given. As there is no way to explicitly specify the end of a parameter name inside the body, a parameter may accidently try to match characters that comes after the parameter. A good rule of thumb is to make use of space to separate entities whenever possible. This also tends to improve readability.

Use of local labels

Each macro expansion will create a new unique context for local labels inside the macro body. Any previous local label context is restored after the macro is expanded. Thus, local labels inside a macro will not clash or interfere with any local labels surrounding the use of the macro.

This also works when using nested macro expansions. If a macro uses another macro inside its body, that inner macro expansion will have its own private local label context, and the previous context of the outer macro expansion will be restored when the inner macro has been expanded.

Thus, you are able to do:

waitfield     .macro field
1$:           c=c-1 \field
              gonc  1$
              .endm

              ldi   100
              waitfield x
1$:           c=0   w

Which would create the following list file:

###############################################################################
#                                                                             #
# Calypsi assembler for Hewlett-Packard Nut                      version 5.16 #
#                                                       14/Apr/2026  16:42:38 #
# Command line: -l macro-local.s                                              #
#                                                                             #
###############################################################################

0001              waitfield     .macro field
0002              1$:           c=c-1 \field
0003                            gonc  1$
0004                            .endm
0005
0006  0000 130064               ldi   100
0007                            waitfield x
    \ 0002 266    `1$`:       c=c-1   x
    \ 0003 3fb                gonc    `1$`
0008  0004 04e    1$:           c=0   w
0009

##########################
#                        #
# Memory sizes (decimal) #
#                        #
##########################

Executable  (Text): 5 words

Arguments with comma

Arguments to a macro are comma separated. This poses a problem in a situation where you want an argument to contain a comma character. The .argdelim directive defines a start and stop character that can be used to create an argument that contains a comma character.

              .argdelim <>
access        .macro  arg1, arg2
              ...
              .endm

              access  0, <2,a>

Here arg1 is bound to 0 and arg2 is bound to the value 2,a.

The delimiter can be either one or two characters and you can pick any suitable character combination. By default there are no delimiter characters defined.

If a single character combination is not suitable, you can use two characters, e.g. <- and -> which would be defined as follows:

              .argdelim <-->
access        .macro  arg1, arg2
              ...
              .endm

              access  0, <-2,a->

All delimiter characters are stripped and arg2 is bound to 2,a here as well.