Macros

MASM macros, parameters, expansion, and small abstractions that still show the machine.

MASM macros run while the assembler is building the program. They can remove repetitive source code, but they expand into real instructions—so a good macro stays small enough that you can still predict the output.

Text aliases and instruction macros

textequ is a textual substitution. A named macro can emit one or more instructions. Neither one is a runtime function call.

Text aliases and instruction macros source/chapters/macros.asm
constantmacro textequ <1911>

clearrax textequ <xor rax, rax>

clearrcx macro
    xor rcx, rcx
endm

Keep in mind: Use a procedure when you want one shared runtime implementation; use a macro when expansion is the point.

Parameters make expansion reusable

:req makes an argument mandatory. A := value provides a default when the caller leaves that parameter out. The assembler substitutes the chosen operands directly into the emitted instructions.

Parameters make expansion reusable source/chapters/macros.asm
macrowparams macro p0:req, p1:=<1911>
    xor p0, p0
    add p0, p1
endm

Keep in mind: Name macro parameters by their role, not by a register you happen to pass today.

Assembly-time branching

Macro conditionals choose what source to emit. They are evaluated during assembly, so this if is not a CPU branch and produces no conditional jump by itself.

Assembly-time branching source/chapters/macros.asm
macrobranching macro num:req
    if num gt 10
        mov rax, 10
    elseif num lt 0
        mov rax, -1
    else
        xor rax, rax
    endif
endm

Keep in mind: Compile-time conditions need values the assembler can know before the program runs.

Call sites should remain readable

The payoff is visible where the macros are used: repeated setup becomes a descriptive line, while ordinary instructions remain ordinary instructions. If a macro call hides too much state, it has grown too large.

Call sites should remain readable source/chapters/macros.asm
    mov rax, constantmacro
    clearrax
    clearrcx
    macrowparams rax, 8
    mov rcx, 2
    macrobranching 1
    macrowhile rax, 100
    macrofor 1, 2, 3
    macrolabels 4, 3
    mov rax, factorial(4)
    mov rbx, factorial(5)
    mov rax, sumargs(1, 2, 3, 4)
    mov rax, sumargs(1, 2, 3, 4, 5, 6, 7, 8)

Keep in mind: Treat macro expansion as code you will eventually debug in a disassembler.

Keep these rules

  • Macros expand at assembly time; procedures execute at runtime.
  • Required and default parameters make macro contracts explicit.
  • Prefer small macros whose emitted instructions remain obvious.