What is a Macro?

A macro is a sequence of instructions or data definitions that you define once and can then reuse multiple times throughout your code by simply typing the macro’s name. When the assembler encounters the macro name, it substitutes the entire predefined block of code in its place.

Macro vs. Subroutine:

  • Subroutine (CALL): Saves memory by running one copy of the code, but is slower because it incurs the overhead of the CALL and RET instructions (17 cycles).
  • Macro: Faster because the code is pasted directly (inline) every time it’s used, but increases the size of the assembled program.

Defining a Simple Macro

The syntax for defining a macro varies slightly between assemblers (e.g., TASM, Z80Asm, sjasmplus), but they typically use MACRO and ENDM or DEFM.

Example: A Custom 16-bit Load Macro

This macro creates a reusable command called LDRR that simplifies loading a 16-bit value into any 16-bit register pair (DE, HL, or BC). The %1 and %2 are parameters supplied by the user.

DEFM LDRR #1, #2        ; Define Macro LDRR with two parameters
    LD   #1, #2          ; Actual instruction sequence
ENDM                       ; End of macro definition

; --- Usage ---
START:
    LDRR DE, 5000H         ; Macro call
    LDRR HL, START_ADDRESS ; Macro call

; The assembler expands the code as:
; LD DE, 5000H
; LD HL, START_ADDRESS

Macros for Complex Tasks

Macros become powerful when they hide complex, multi-line logic behind a simple command.

Example: The Safe Stack-Swap Macro

This macro quickly swaps the contents of two register pairs (HL and DE) without overwriting memory outside the stack.

DEFM SWAP_HLDE
    PUSH HL             ; Save HL
    PUSH DE             ; Save DE
    POP  HL             ; HL gets DE's original value
    POP  DE             ; DE gets HL's original value
ENDM

; --- Usage ---
    SWAP_HLDE           ; Swaps the contents of HL and DE in 4 instructions

Debugging Macros: Always check your assembler’s listing file (if available). The listing file shows the original source code alongside the expanded machine code, which is essential for catching errors in your macro logic.