Skip to main content

Merlin Assembler Syntax Reference

Target Systems: Apple II series (II+, IIe, IIc, IIgs) CPU Support: 6502, 65C02, 65802, 65816 Versions Covered: Merlin 8, Merlin 16, Merlin Pro Purpose: Complete syntax reference for xasm++ Merlin compatibility


Table of Contents​


Overview​

Merlin is a professional macro assembler for the 6502 family, originally developed by Glen Bredon for Apple II computers. It provides comprehensive support for:

  • 6502 - Standard 6502 instruction set
  • 65C02 - CMOS enhancements (via XC directive)
  • 65802/65816 - 16-bit extensions (Merlin Pro)
  • Macros - Parameter substitution and expansion
  • Conditional Assembly - DO/ELSE/FIN blocks
  • Relocatable Code - REL/ENT/EXT support
  • 50+ Pseudo-Opcodes - Extensive directive set

Key Philosophy: Simple, powerful, and compatible with Apple II development conventions.


Version Differences​

Merlin 8 (Original)​

Features:

  • 6502 instruction set only
  • 8-character label limit
  • Basic pseudo-opcodes (ORG, EQU, DFB, DA, ASC, HEX, etc.)
  • Macro support with ]1-]9 parameters
  • DOS 3.3 file operations

Limitations:

  • No 65C02 support
  • DDB byte order varies

Merlin 16 (Enhanced)​

Enhancements over Merlin 8:

  • 65C02 support via XC directive
  • 16-character labels
  • Additional string directives (STR, REV, DCI)
  • Relocatable code (REL, ENT, EXT, USE)
  • ProDOS pathname support
  • Consistent DDB byte order (big-endian)

Merlin Pro (Professional)​

Enhancements over Merlin 16:

  • Full 65816 support (16-bit mode)
  • MX directive for register size tracking
  • Long addressing modes
  • Enhanced macro capabilities
  • Source-level debugger integration
  • ProDOS 16 support

Recommended: Use Merlin Pro features as baseline for maximum compatibility.


Source Line Format​

Line Structure​

[label] [opcode] [operand] [;comment]

Fields:

  1. Label (optional): Starts in column 1, alphanumeric + _, ends with whitespace or :
  2. Opcode (required): CPU instruction or pseudo-opcode
  3. Operand (optional): Expression, addressing mode specifier, or directive parameter
  4. Comment (optional): Text following ; or * in column 1

Examples​

START    LDA  #$00        ;Initialize accumulator
STA $C000 ;Store to hardware
LOOP INC COUNT ;Increment counter
BNE LOOP ;Branch if not zero
*
* Block comment using asterisk in column 1
*
RTS ;Return

Blank Lines​

Blank lines are allowed and ignored. Use for readability.

Column Rules​

  • Column 1: Reserved for labels or * comment
  • Whitespace: Tabs or spaces separate fields (typically one tab)
  • Case: Instructions are case-insensitive; labels are case-sensitive in some contexts

Number Formats​

Decimal (Default)​

Numbers without prefix are decimal:

    LDA  #100        ;Decimal 100
DFB 255 ;Decimal 255

Hexadecimal ($)​

Prefix with dollar sign:

    LDA  #$FF        ;Hex FF (255 decimal)
STA $C000 ;Address $C000
DFB $20,$30,$40 ;Multiple hex bytes

Binary (%)​

Prefix with percent sign:

    LDA  #%10101010  ;Binary 170
AND #%11110000 ;Binary mask

ASCII Character (')​

Single character in single quotes:

    LDA  #'A         ;ASCII 'A' (65)
CMP #'Z ;ASCII 'Z' (90)

High-bit variants:

  • 'A - Normal ASCII (0x41)
  • "A - With high bit set (0xC1) - Note: Some variants

Expressions​

Operators​

Precedence (highest to lowest):

LevelOperatorsDescription
4< > ^Low byte, high byte, bank byte (unary)
3* /Multiply, divide
2+ -Add, subtract
1& . !Bitwise AND, OR, XOR

Parentheses () override precedence.

Byte Extraction Operators​

  • <expression - Low byte (bits 0-7)
  • >expression - High byte (bits 8-15)
  • ^expression - Bank byte (bits 16-23, 65816 only)
ADDR     EQU  $1234
LOBYTE EQU <ADDR ;Result: $34
HIBYTE EQU >ADDR ;Result: $12

Bitwise Operators​

  • & - Bitwise AND
  • . - Bitwise OR (period)
  • ! - Bitwise XOR
MASK1    EQU  $F0
MASK2 EQU $0F
BOTH EQU MASK1&MASK2 ;Result: $00
EITHER EQU MASK1.MASK2 ;Result: $FF

Special Symbols​

  • * - Current program counter value
  • ]N - Macro parameter (N = 1-9)
HERE     EQU  *           ;Save current address
OFFSET EQU TARGET-* ;Distance to target
BNE *+5 ;Branch forward 5 bytes

Evaluation Rules​

  • Left-to-right within same precedence (unlike algebraic)
  • Example: 10+5*2 = 20 (not 20 as in algebra)
  • Use parentheses: 10+(5*2) = 20

Addressing Modes​

Mode Summary Table​

ModeSyntaxExampleBytesNotes
ImpliedopcNOP1No operand
Accumulatoropc AASL A1Optional A
Immediate#exprLDA #$202Literal value
AbsoluteexprLDA $1000316-bit address
Absolute,Xexpr,XLDA $1000,X3Indexed by X
Absolute,Yexpr,YLDA $1000,Y3Indexed by Y
Zero PageexprLDA $202Auto if < $100
Zero Page,Xexpr,XLDA $20,X2ZP indexed X
Zero Page,Yexpr,YLDX $20,Y2ZP indexed Y
Indirect(expr)JMP ($1000)3Pointer jump
(Indirect,X)(expr,X)LDA ($20,X)2Pre-indexed
(Indirect),Y(expr),YLDA ($20),Y2Post-indexed
RelativelabelBNE LOOP2Auto-calc offset

65C02 Additional Modes​

ModeSyntaxExampleNotes
(Zero Page)(expr)LDA ($20)ZP indirect
(Absolute,X)(expr,X)JMP ($1000,X)Indexed indirect JMP

65816 Long Addressing​

ModeSyntaxExampleNotes
Absolute LongexprLDA $01000024-bit address
Absolute Long,Xexpr,XLDA $010000,X24-bit + X
[Direct Indirect][expr]LDA [$20]24-bit pointer
[Direct],Y[expr],YLDA [$20],Y24-bit ptr + Y
Stack Relativeexpr,SLDA $02,SStack offset
(SR,S),Y(expr,S),YLDA ($02,S),YSR indirect + Y

Force Addressing Mode​

Prefix operators override automatic mode selection:

  • < - Force zero page (2 bytes)
  • > - Force absolute (3 bytes)
  • >> - Force long (4 bytes, 65816)
VALUE    EQU  $05
LDA VALUE ;Auto: zero page (2 bytes)
LDA >VALUE ;Force: absolute (3 bytes)
LDA >>VALUE ;Force: long (4 bytes, 65816)

Pseudo-Opcodes Reference​

Assembly Control​

ORG - Set Origin​

Syntax: ORG expression

Set assembly address:

         ORG  $8000       ;Assemble at $8000

Can be used multiple times to create non-contiguous sections.

END - End Assembly​

Syntax: END

Mark end of source file (optional in most contexts).

Symbol Definition​

EQU - Equate Symbol​

Syntax: label EQU expression

Define constant symbol:

MAXVAL   EQU  255         ;Define constant
IOPORT EQU $C000 ;I/O address
OFFSET EQU END-START ;Computed value

Cannot be redefined. Use = for variables.

= - Variable Assignment​

Syntax: label = expression

Define or reassign variable:

COUNTER  =    0           ;Initialize
COUNTER = COUNTER+1 ;Increment

Can be redefined, unlike EQU.

Data Generation​

DFB - Define Byte​

Syntax: DFB byte[,byte...]

Generate byte values:

         DFB  $20              ;Single byte
DFB $20,$30,$40 ;Multiple bytes
DFB <ADDR,>ADDR ;Low/high bytes

Aliases: DB, FCB (some variants)

DA - Define Address (Word)​

Syntax: DA address[,address...]

Generate 16-bit addresses (little-endian):

         DA   $1000            ;Stores $00,$10
DA LABEL1,LABEL2 ;Multiple addresses
DA * ;Current PC

Aliases: DW (some variants)

DDB - Define Double Byte​

Syntax: DDB value[,value...]

Generate 16-bit values:

         DDB  $1234            ;Big-endian: $12,$34

Note: Byte order is big-endian in Merlin 16/Pro, may vary in Merlin 8.

HEX - Hexadecimal Bytes​

Syntax: HEX hex-digits

Compact hex notation (no $ prefix):

         HEX  20304050         ;4 bytes: $20,$30,$40,$50
HEX FF,00 ;With commas
HEX A0A1A2 ;3 bytes

Rules:

  • Even number of hex digits
  • No $ prefix
  • Case insensitive

ASC - ASCII String​

Syntax: ASC "string" or ASC 'string'

Generate ASCII string:

         ASC  "HELLO WORLD"    ;Plain ASCII
ASC 'Text' ;Single quotes OK

Embedded hex:

         ASC  "Line 1"8D       ;String + CR byte

DCI - Define Character Inverted​

Syntax: DCI "string"

Last character has high bit inverted:

         DCI  "HELLO"          ;HELL-O (O = $CF not $4F)

Use case: String termination marker.

INV - Inverse String​

Syntax: INV "string"

All characters have high bit set:

         INV  "FLASH"          ;All bytes $80-$FF range

REV - Reverse String​

Syntax: REV "string"

String stored in reverse order:

         REV  "HELLO"          ;Stores "OLLEH"

STR - Pascal String​

Syntax: STR "string"

Length-prefixed string:

         STR  "HELLO"          ;Stores: $05,"HELLO"

Length byte = string length (max 255).

DS - Define Storage​

Syntax: DS size[,fill]

Reserve bytes:

         DS   100              ;100 bytes (unfilled)
DS 256,$FF ;256 bytes of $FF
DS \ ;Align to page boundary

Special: DS \ advances to next page boundary.

Listing Control​

LST - Listing Control​

Syntax: LST [ON|OFF|RTN]

         LST  OFF              ;Disable listing
LST ON ;Enable listing
LST RTN ;Suppress macro expansion

PAG - Page Eject​

Syntax: PAG

Force new page in listing.

TTL - Title​

Syntax: TTL "title"

Set listing page title:

         TTL  "Main Program"

SKP - Skip Lines​

Syntax: SKP n

Insert n blank lines in listing:

         SKP  3                ;3 blank lines

Conditional Assembly​

DO - Begin Conditional​

Syntax: DO expression

Assemble if expression ≠ 0:

DEBUG    EQU  1
DO DEBUG ;Assemble if DEBUG set
JSR TRACE
FIN

ELSE - Conditional Else​

Syntax: ELSE

Alternate block for DO:

         DO   VERSION-2
JSR NEWCODE ;If VERSION=2
ELSE
JSR OLDCODE ;If VERSION≠2
FIN

FIN - End Conditional​

Syntax: FIN

End DO/ELSE block.

Macro Directives​

MAC - Begin Macro​

Syntax: label MAC

Define macro:

MOVE     MAC                   ;Define MOVE macro
LDA ]1 ;Parameter 1
STA ]2 ;Parameter 2
EOM ;End macro

Note: Some variants use .MA instead of MAC.

EOM - End Macro​

Syntax: EOM or \<\<\<

End macro definition.

PMC - Print Macro​

Syntax: PMC [ON|OFF]

Control macro expansion in listing:

         PMC  ON               ;Show expansion
PMC OFF ;Hide expansion

Relocatable Code​

REL - Relocatable​

Syntax: REL

Begin relocatable code section:

         REL                   ;Start relocatable
LDA BUFFER ;Uses relocatable addr

ENT - Entry Point​

Syntax: ENT symbol[,symbol...]

Export symbols for linker:

         ENT  MAIN,INIT        ;Export these

EXT - External Reference​

Syntax: EXT symbol[,symbol...]

Import symbols from other modules:

         EXT  PRINT,GETLN      ;Import these

USE - Use Object File​

Syntax: USE filename

Link with object file.

File Operations​

PUT - Include File​

Syntax: PUT filename

Include source file:

         PUT  MACROS           ;Include macros
PUT LIBRARY ;Include library

SAV - Save Object​

Syntax: SAV filename

Specify output file:

         SAV  MYPROG           ;Save as MYPROG

CPU Selection​

XC - CPU Mode​

Syntax: XC [ON|OFF]

Enable 65C02 instructions:

         XC                    ;Enable 65C02
STZ $00 ;Now legal
XC OFF ;Back to 6502

Merlin Pro: XC 65816 for 65816 mode.

MX - Register Size (65816)​

Syntax: MX %mb

Set 65816 register size flags:

         MX   %00              ;16-bit A, 16-bit X/Y
MX %10 ;8-bit A, 16-bit X/Y
MX %11 ;8-bit A, 8-bit X/Y

Bits:

  • Bit 1 (m): M flag (0=16-bit A, 1=8-bit A)
  • Bit 0 (b): X flag (0=16-bit X/Y, 1=8-bit X/Y)

Critical: MX doesn't generate code, only tells assembler immediate operand size.


String Handling​

Delimiter Rules​

Strings use matching delimiters:

         ASC  "Text in double quotes"
ASC 'Text in single quotes'
ASC /Text with slashes/

High Bit Control​

Normal ASCII (high bit clear):

         ASC  "HELLO"          ;$48,$45,$4C,$4C,$4F

Inverse/Flash (high bit set):

         INV  "HELLO"          ;$C8,$C5,$CC,$CC,$CF

Last character marked:

         DCI  "HELLO"          ;$48,$45,$4C,$4C,$CF

Embedded Hex​

Insert raw hex in strings:

         ASC  "Line 1"8D       ;String + CR
ASC "Text"00 ;Null-terminated

Format: Two hex digits (no $ prefix) between string segments.

Control Characters​

Special sequences for control codes:

         ASC  "Press ^M"       ;^M = RETURN ($0D)
ASC "ESC^[" ;^[ = ESC ($1B)

Supported: ^A through ^Z, ^[, ^], ^\, ^^, ^_


Label Rules​

Valid Labels​

First character: Letter (A-Z, a-z) Subsequent: Letters, digits, underscore Length: 8 chars (Merlin 8), 16 chars (Merlin 16/Pro) Terminator: Whitespace or colon (optional)

START              ;Basic label
LOOP1 ;With digit
MY_ROUTINE ;With underscore
Label: ;With colon

Invalid Labels​

1LABEL             ;Cannot start with digit
MY-LABEL ;Hyphen not allowed
VERYLONGLABELNAME ;Too long (>16 chars)
LDA ;Cannot match mnemonic
ORG ;Cannot match pseudo-op

Local Labels​

Format: :NAME or ]NAME (Merlin Pro)

ROUTINE  LDA  #$00
:LOOP STA $C000,X ;Local label
INX
BNE :LOOP ;Reference local
RTS

NEXT LDA #$01
:LOOP STA $C001,X ;Different :LOOP
INX
BNE :LOOP
RTS

Scope: Reset at next global label.

Anonymous Labels​

Format: ^ (forward) or - (backward)

         LDA  #$00
^ STA $C000,X ;Define forward label
INX
BNE ^ ;Branch to it

Note: Not all Merlin versions support anonymous labels.


Macro System​

Macro Definition​

MACRONAME MAC                 ;Begin definition
; ... macro body ...
; Use ]1-]9 for parameters
EOM ;End definition

Parameter Substitution​

Parameters referenced as ]1 through ]9:

STORE    MAC                   ;Define STORE macro
LDA ]1 ;First parameter
STA ]2 ;Second parameter
EOM

; Invocation:
STORE #$42,BUFFER ;Generates: LDA #$42; STA BUFFER

Macro Label Parameter​

]0 contains the macro invocation label (if any):

WAIT     MAC
]0.LOOP DEX ;Use ]0 as label prefix
BNE ]0.LOOP
EOM

; Invocation:
WAIT1 WAIT ;Generates WAIT1.LOOP label
WAIT2 WAIT ;Generates WAIT2.LOOP label

Nested Macros​

Macros can invoke other macros:

INNER    MAC
LDA ]1
EOM

OUTER MAC
INNER ]1 ;Call INNER
STA ]2
EOM

OUTER $10,$20 ;Expands both

Listing Control​

         PMC  OFF              ;Hide macro expansion
MYMACRO ARG1,ARG2 ;Only show invocation
PMC ON ;Resume expansion display

Conditional Assembly​

Basic Structure​

         DO   condition
; ... code if condition ≠ 0 ...
FIN

With ELSE​

         DO   condition
; ... code if condition ≠ 0 ...
ELSE
; ... code if condition = 0 ...
FIN

Nesting​

Conditionals can be nested:

         DO   PLATFORM-1
DO DEBUG
JSR APPLE_DEBUG
FIN
FIN

Common Patterns​

Feature flags:

DEBUG    EQU  1
DO DEBUG
JSR TRACE
FIN

Version selection:

VERSION  EQU  2
DO VERSION-2
JSR V2CODE
ELSE
JSR V1CODE
FIN

Platform targeting:

APPLE2E  EQU  1
DO APPLE2E
LDA $C000,X ;//e specific
ELSE
LDA $C000 ;Standard
FIN

65816 Features​

Enabling 65816 Mode​

         XC   65816            ;Enable 65816 (Merlin Pro)

Register Size Tracking​

MX Directive: Tell assembler current register sizes

         REP  #$30             ;16-bit A, X, Y (in code)
MX %00 ;Tell assembler
LDA #$1234 ;Now 16-bit immediate
LDX #$5678 ;16-bit immediate

SEP #$20 ;8-bit A (in code)
MX %10 ;Tell assembler
LDA #$12 ;Now 8-bit immediate

Critical: MX directive doesn't generate code - programmer must manually track REP/SEP.

Long Addressing​

24-bit addresses:

         LDA  $123456          ;Load from bank $12, addr $3456
LDA $010000,X ;Bank 1 with X offset

Long indirect:

         LDA  [$20]            ;24-bit pointer at DP $20
LDA [$20],Y ;Plus Y offset

Stack relative:

         LDA  $02,S            ;Load from stack offset
LDA ($02,S),Y ;Stack relative indirect

Additional 65816 Instructions​

Stack operations:

         PEA  $1234            ;Push 16-bit literal
PER LABEL ;Push effective address
PHB ;Push data bank
PHD ;Push direct page
PHK ;Push program bank

Long jumps:

         JML  $020000          ;Jump long
JSL $010000 ;Call long subroutine
RTL ;Return long

Register transfers:

         TCD                   ;C to D
TCS ;C to S
TDC ;D to C
TSC ;S to C
TXY ;X to Y
TYX ;Y to X
XBA ;Exchange B and A
XCE ;Exchange C and E

Block moves:

         MVN  $12,$34          ;Move next (increment)
MVP $12,$34 ;Move previous (decrement)

Processor control:

         REP  #$30             ;Reset status bits
SEP #$20 ;Set status bits
COP ;Coprocessor
WDM ;Reserved

Quick Reference Tables​

Pseudo-Opcode Summary​

DirectivePurposeExample
Assembly Control
ORGSet originORG $8000
ENDEnd assemblyEND
Symbol Definition
EQUDefine constantMAXVAL EQU 255
=Define variableCOUNT = 0
Data Generation
DFB/DBDefine byte(s)DFB $20,$30
DA/DWDefine addressDA ROUTINE
DDBDefine word (BE)DDB $1234
HEXHex bytesHEX 010203
ASCASCII stringASC "TEXT"
DCIString, last invDCI "TEXT"
INVInverse stringINV "TEXT"
REVReverse stringREV "TEXT"
STRPascal stringSTR "TEXT"
DSReserve spaceDS 256
Listing
LSTListing controlLST OFF
PAGPage ejectPAG
TTLSet titleTTL "Title"
SKPSkip linesSKP 3
Conditional
DOBegin conditionalDO DEBUG
ELSEAlternate blockELSE
FINEnd conditionalFIN
Macros
MACBegin macroMOVE MAC
EOM/<<<End macroEOM
PMCPrint macroPMC OFF
Relocatable
RELRelocatable modeREL
ENTEntry pointENT MAIN
EXTExternal refEXT PRINT
USEUse objectUSE LIBRARY
Files
PUTInclude filePUT MACROS
SAVSave objectSAV OUTPUT
CPU
XCCPU modeXC 65816
MXRegister sizeMX %00

Number Format Quick Reference​

FormatSyntaxExampleValue
Decimalnnn255255
Hexadecimal$hh$FF255
Binary%bbbb%11111111255
ASCII'c'A65

Operator Precedence​

LevelOperatorsExample
4 (high)< > ^<$1234 = $34
3* /10*5 = 50
2+ -10+5 = 15
1 (low)& . !$F0&$0F = $00

Addressing Mode Byte Counts​

ModeBytesExample
Implied1NOP
Accumulator1ASL A
Immediate2LDA #$20
Zero Page2LDA $20
Zero Page,X/Y2LDA $20,X
Absolute3LDA $1000
Absolute,X/Y3LDA $1000,X
(Indirect,X)2LDA ($20,X)
(Indirect),Y2LDA ($20),Y
Indirect3JMP ($1000)
Relative2BNE LOOP
65816 Long
Absolute Long4LDA $123456
Long,X4LDA $123456,X
[Direct]2LDA [$20]
[Direct],Y2LDA [$20],Y

Implementation Notes for xasm++​

Critical Parsing Rules​

  1. Expression Evaluation: Left-to-right within same precedence level
  2. Addressing Mode Selection: Auto-detect ZP vs absolute based on value
  3. String Delimiters: Support multiple delimiter types
  4. Macro Expansion: Parameter substitution with ]0-]9
  5. Conditional Nesting: Track DO/ELSE/FIN depth

Two-Pass Assembly​

Pass 1: Collect symbols, resolve forward references Pass 2: Generate code, check all references resolved

Version-Specific Features​

  • Merlin 8: 8-char labels, DDB byte order caution
  • Merlin 16: 16-char labels, relocatable code, consistent DDB
  • Merlin Pro: 65816 support, MX directive, long addressing

Testing Recommendations​

  1. Test with original Merlin source files (Prince of Persia, etc.)
  2. Verify all addressing modes with real code
  3. Test macro expansion with nested invocations
  4. Verify MX directive interaction with immediate values
  5. Test string handling (ASC, DCI, INV, REV, STR)
  6. Verify expression evaluation order
  7. Test conditional assembly with nesting

References​

  • Merlin 8/16 Manual - Glen Bredon, Roger Wagner Publishing
  • Merlin Pro Manual - Professional edition documentation
  • 65816 Programming Manual - WDC 65816 reference
  • Apple II Reference Manual - Apple Computer, Inc.

Document Version: 1.0 Created: 2026-01-29 For: xasm++ Merlin compatibility implementation Maintainer: xasm++ development team