<title>ca65 Users Guide
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
-<date>2016-06-11
<abstract>
ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is
<itemize>
-<item> The assembler must support macros. Macros are not essential, but they
- make some things easier, especially when you use the assembler in the
- backend of a compiler.
-<item> The assembler must support the newer 65C02 and 65816 CPUs. I have been
- thinking about a 65816 backend for the C compiler, and even my old
- a816 assembler had support for these CPUs, so this wasn't really a
- problem.
-<item> The assembler must produce relocatable code. This is necessary for the
- compiler support, and it is more convenient.
-<item> Conditional assembly must be supported. This is a must for bigger
- projects written in assembler (like Elite128).
-<item> The assembler must support segments, and it must support more than
- three segments (this is the count, most other assemblers support).
- Having more than one code segments helps developing code for systems
- with a divided ROM area (like the C64).
-<item> The linker must be able to resolve arbitrary expressions. It should
- be able to get things like
+<item> The assembler must support macros. Macros are not essential, but they
+ make some things easier, especially when you use the assembler in the
+ backend of a compiler.
+<item> The assembler must support the newer 65C02 and 65816 CPUs. I have been
+ thinking about a 65816 backend for the C compiler, and even my old
+ a816 assembler had support for these CPUs, so this wasn't really a
+ problem.
+<item> The assembler must produce relocatable code. This is necessary for the
+ compiler support, and it is more convenient.
+<item> Conditional assembly must be supported. This is a must for bigger
+ projects written in assembler (like Elite128).
+<item> The assembler must support segments, and it must support more than
+ three segments (this is the count, most other assemblers support).
+ Having more than one code segments helps developing code for systems
+ with a divided ROM area (like the C64).
+<item> The linker must be able to resolve arbitrary expressions. It should
+ be able to get things like
<tscreen><verb>
- .import S1, S2
- .export Special
- Special = 2*S1 + S2/7
+ .import S1, S2
+ .export Special
+ Special = 2*S1 + S2/7
</verb></tscreen>
- right.
-<item> True lexical nesting for symbols. This is very convenient for larger
- assembly projects.
-<item> "Cheap" local symbols without lexical nesting for those quick, late
- night hacks.
-<item> I liked the idea of "options" as Anre Fachats .o65 format has it, so I
- introduced the concept into the object file format use by the new cc65
- binutils.
-<item> The assembler will be a one pass assembler. There was no real need for
- this decision, but I've written several multipass assemblers, and it
- started to get boring. A one pass assembler needs much more elaborated
- data structures, and because of that it's much more fun:-)
-<item> Non-GPLed code that may be used in any project without restrictions or
- fear of "GPL infecting" other code.
+ right.
+<item> True lexical nesting for symbols. This is very convenient for larger
+ assembly projects.
+<item> "Cheap" local symbols without lexical nesting for those quick, late
+ night hacks.
+<item> I liked the idea of "options" as Anre Fachats .o65 format has it, so I
+ introduced the concept into the object file format use by the new cc65
+ binutils.
+<item> The assembler will be a one pass assembler. There was no real need for
+ this decision, but I've written several multipass assemblers, and it
+ started to get boring. A one pass assembler needs much more elaborated
+ data structures, and because of that it's much more fun:-)
+<item> Non-GPLed code that may be used in any project without restrictions or
+ fear of "GPL infecting" other code.
</itemize>
<p>
Set the default for the CPU type. The option takes a parameter, which
may be one of
- 6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
+ 6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
<label id="option-create-dep">
Here are some examples for valid input lines:
<tscreen><verb>
- Label: ; A label and a comment
- lda #$20 ; A 6502 instruction plus comment
- L1: ldx #$20 ; Same with label
- L2: .byte "Hello world" ; Label plus control command
- mymac $20 ; Macro expansion
- MySym = 3*L1 ; Symbol definition
- MaSym = Label ; Another symbol
+ Label: ; A label and a comment
+ lda #$20 ; A 6502 instruction plus comment
+ L1: ldx #$20 ; Same with label
+ L2: .byte "Hello world" ; Label plus control command
+ mymac $20 ; Macro expansion
+ MySym = 3*L1 ; Symbol definition
+ MaSym = Label ; Another symbol
</verb></tscreen>
The assembler accepts
expression:
<itemize>
-<item> If the result of an expression is constant, the actual value is
- checked to see if it's a byte sized expression or not.
-<item> If the expression is explicitly casted to a byte sized expression by
- one of the '>', '<' or '^' operators, it is a byte expression.
-<item> If this is not the case, and the expression contains a symbol,
- explicitly declared as zero page symbol (by one of the .importzp or
- .exportzp instructions), then the whole expression is assumed to be
- byte sized.
-<item> If the expression contains symbols that are not defined, and these
- symbols are local symbols, the enclosing scopes are searched for a
- symbol with the same name. If one exists and this symbol is defined,
- its attributes are used to determine the result size.
-<item> In all other cases the expression is assumed to be word sized.
+<item> If the result of an expression is constant, the actual value is
+ checked to see if it's a byte sized expression or not.
+<item> If the expression is explicitly casted to a byte sized expression by
+ one of the '>', '<' or '^' operators, it is a byte expression.
+<item> If this is not the case, and the expression contains a symbol,
+ explicitly declared as zero page symbol (by one of the .importzp or
+ .exportzp instructions), then the whole expression is assumed to be
+ byte sized.
+<item> If the expression contains symbols that are not defined, and these
+ symbols are local symbols, the enclosing scopes are searched for a
+ symbol with the same name. If one exists and this symbol is defined,
+ its attributes are used to determine the result size.
+<item> In all other cases the expression is assumed to be word sized.
</itemize>
Note: If the assembler is not able to evaluate the expression at assembly
names like "Loop". Here is an example:
<tscreen><verb>
- Clear: lda #$00 ; Global label
- ldy #$20
- @Loop: sta Mem,y ; Local label
- dey
- bne @Loop ; Ok
- rts
- Sub: ... ; New global label
- bne @Loop ; ERROR: Unknown identifier!
+ Clear: lda #$00 ; Global label
+ ldy #$20
+ @Loop: sta Mem,y ; Local label
+ dey
+ bne @Loop ; Ok
+ rts
+ Sub: ... ; New global label
+ bne @Loop ; ERROR: Unknown identifier!
</verb></tscreen>
<sect1>Unnamed labels<p>
understand this:
<tscreen><verb>
- : lda (ptr1),y ; #1
- cmp (ptr2),y
- bne :+ ; -> #2
- tax
- beq :+++ ; -> #4
- iny
- bne :- ; -> #1
- inc ptr1+1
- inc ptr2+1
- bne :- ; -> #1
-
- : bcs :+ ; #2 -> #3
- ldx #$FF
- rts
-
- : ldx #$01 ; #3
- : rts ; #4
+ : lda (ptr1),y ; #1
+ cmp (ptr2),y
+ bne :+ ; -> #2
+ tax
+ beq :+++ ; -> #4
+ iny
+ bne :- ; -> #1
+ inc ptr1+1
+ inc ptr2+1
+ bne :- ; -> #1
+
+ : bcs :+ ; #2 -> #3
+ ldx #$FF
+ rts
+
+ : ldx #$01 ; #3
+ : rts ; #4
</verb></tscreen>
As you can see from the example, unnamed labels will make even short
Example:
<tscreen><verb>
- .DEFINE two 2
- .DEFINE version "SOS V2.3"
+ .DEFINE two 2
+ .DEFINE version "SOS V2.3"
- four = two * two ; Ok
- .byte version ; Ok
+ four = two * two ; Ok
+ .byte version ; Ok
- .PROC ; Start local scope
- two = 3 ; Will give "2 = 3" - invalid!
- .ENDPROC
+ .PROC ; Start local scope
+ two = 3 ; Will give "2 = 3" - invalid!
+ .ENDPROC
</verb></tscreen>
<sect1>Address sizes of symbols<p>
+The address size of a symbol can be specified with a prefix:
+<itemize>
+<item>z: zeropage addressing (8 bits).
+<item>a: absolute addressing (16 bits).
+<item>f: far addressing (24 bits).
+</itemize>
+
+The zeropage addressing override can be used to ensure the use of optimal
+zeropage instructions, or correct cases where the size isn't yet known
+due to the single-pass assembly model.
+
+The larger addressing overrides can be used to promote a smaller address
+to absolute or far addressing, instead of being automatically fit into
+a smaller addressing type.
<sect1>Memory models<p>
Example:
<tscreen><verb>
- ; Reverse Subtract with Accumulator
- ; A = memory - A
- .macro rsb param
- .if .asize = 8
- eor #$ff
- .else
- eor #$ffff
- .endif
- sec
- adc param
- .endmacro
+ ; Reverse Subtract with Accumulator
+ ; A = memory - A
+ .macro rsb param
+ .if .asize = 8
+ eor #$ff
+ .else
+ eor #$ffff
+ .endif
+ sec
+ adc param
+ .endmacro
</verb></tscreen>
See also: <tt><ref id=".ISIZE" name=".ISIZE"></tt>
<tscreen><verb>
.macpack cpu
- .if (.cpu .bitand CPU_ISET_65816)
- phx
- phy
- .else
- txa
- pha
- tya
- pha
- .endif
+ .if (.cpu .bitand CPU_ISET_65816)
+ phx
+ phy
+ .else
+ txa
+ pha
+ tya
+ pha
+ .endif
</verb></tscreen>
Example:
<tscreen><verb>
- .macro foo arg1, arg2, arg3
- .if .paramcount <> 3
- .error "Too few parameters for macro foo"
- .endif
- ...
- .endmacro
+ .macro foo arg1, arg2, arg3
+ .if .paramcount <> 3
+ .error "Too few parameters for macro foo"
+ .endif
+ ...
+ .endmacro
</verb></tscreen>
See section <ref id="macros" name="Macros">.
.endproc
.proc bank_table
- .addr banked_func_1
+ .addr banked_func_1
.byte <.BANK (banked_func_1)
.addr banked_func_2
As an example, the <tt/.IFBLANK/ statement may be replaced by
<tscreen><verb>
- .if .blank({arg})
+ .if .blank({arg})
</verb></tscreen>
Example:
<tscreen><verb>
- .include .concat ("myheader", ".", "inc")
+ .include .concat ("myheader", ".", "inc")
</verb></tscreen>
This is the same as the command
<tscreen><verb>
- .include "myheader.inc"
+ .include "myheader.inc"
</verb></tscreen>
otherwise. As an example, the .IFCONST statement may be replaced by
<tscreen><verb>
- .if .const(a + 3)
+ .if .const(a + 3)
</verb></tscreen>
Example:
<tscreen><verb>
- .macro makelabel arg1, arg2
+ .macro makelabel arg1, arg2
.ident (.concat (arg1, arg2)):
.endmacro
Syntax:
<tscreen><verb>
- .LEFT (<int expr>, <token list>)
+ .LEFT (<int expr>, <token list>)
</verb></tscreen>
The first integer expression gives the number of tokens to extract from
(immediate addressing mode), use something like this:
<tscreen><verb>
- .macro ldax arg
- ...
- .if (.match (.left (1, {arg}), #))
+ .macro ldax arg
+ ...
+ .if (.match (.left (1, {arg}), #))
- ; ldax called with immediate operand
- ...
+ ; ldax called with immediate operand
+ ...
- .endif
- ...
- .endmacro
+ .endif
+ ...
+ .endmacro
</verb></tscreen>
See also the <tt><ref id=".MID" name=".MID"></tt> and <tt><ref id=".RIGHT"
The syntax is
<tscreen><verb>
- .MATCH(<token list #1>, <token list #2>)
+ .MATCH(<token list #1>, <token list #2>)
</verb></tscreen>
Both token list may contain arbitrary tokens with the exception of the
to check for this and print and error for invalid calls.
<tscreen><verb>
- .macro asr arg
+ .macro asr arg
- .if (.not .blank(arg)) .and (.not .match ({arg}, a))
- .error "Syntax error"
- .endif
+ .if (.not .blank(arg)) .and (.not .match ({arg}, a))
+ .error "Syntax error"
+ .endif
- cmp #$80 ; Bit 7 into carry
- lsr a ; Shift carry into bit 7
+ cmp #$80 ; Bit 7 into carry
+ lsr a ; Shift carry into bit 7
- .endmacro
+ .endmacro
</verb></tscreen>
The macro will only accept no arguments, or one argument that must be the
The syntax is
<tscreen><verb>
- .MAX (<value #1>, <value #2>)
+ .MAX (<value #1>, <value #2>)
</verb></tscreen>
Example:
<tscreen><verb>
; Reserve space for the larger of two data blocks
- savearea: .max (.sizeof (foo), .sizeof (bar))
+ savearea: .res .max (.sizeof (foo), .sizeof (bar))
</verb></tscreen>
See: <tt><ref id=".MIN" name=".MIN"></tt>
Syntax:
<tscreen><verb>
- .MID (<int expr>, <int expr>, <token list>)
+ .MID (<int expr>, <int expr>, <token list>)
</verb></tscreen>
The first integer expression gives the starting token in the list (the first
(immediate addressing mode), use something like this:
<tscreen><verb>
- .macro ldax arg
- ...
- .if (.match (.mid (0, 1, {arg}), #))
+ .macro ldax arg
+ ...
+ .if (.match (.mid (0, 1, {arg}), #))
- ; ldax called with immediate operand
- ...
+ ; ldax called with immediate operand
+ ...
- .endif
- ...
- .endmacro
+ .endif
+ ...
+ .endmacro
</verb></tscreen>
See also the <tt><ref id=".LEFT" name=".LEFT"></tt> and <tt><ref id=".RIGHT"
The syntax is
<tscreen><verb>
- .MIN (<value #1>, <value #2>)
+ .MIN (<value #1>, <value #2>)
</verb></tscreen>
Example:
<tscreen><verb>
- ; Reserve space for some data, but 256 bytes minimum
- savearea: .min (.sizeof (foo), 256)
+ ; Reserve space for some data, but 256 bytes maximum
+ savearea: .res .min (.sizeof (foo), 256)
</verb></tscreen>
See: <tt><ref id=".MAX" name=".MAX"></tt>
the <tt><ref id=".IFREF" name=".IFREF"></tt> statement may be replaced by
<tscreen><verb>
- .if .referenced(a)
+ .if .referenced(a)
</verb></tscreen>
See: <tt><ref id=".DEFINED" name=".DEFINED"></tt>
Syntax:
<tscreen><verb>
- .RIGHT (<int expr>, <token list>)
+ .RIGHT (<int expr>, <token list>)
</verb></tscreen>
The first integer expression gives the number of tokens to extract from the
Example:
<tscreen><verb>
- .macro M Arg
- ; Check if the argument string starts with '#'
- .if (.strat (Arg, 0) = '#')
- ...
- .endif
- .endmacro
+ .macro M Arg
+ ; Check if the argument string starts with '#'
+ .if (.strat (Arg, 0) = '#')
+ ...
+ .endif
+ .endmacro
</verb></tscreen>
Example:
<tscreen><verb>
- ; Emulate other assemblers:
- .macro section name
- .segment .string(name)
- .endmacro
+ ; Emulate other assemblers:
+ .macro section name
+ .segment .string(name)
+ .endmacro
</verb></tscreen>
a leading length byte.
<tscreen><verb>
- .macro PString Arg
- .byte .strlen(Arg), Arg
- .endmacro
+ .macro PString Arg
+ .byte .strlen(Arg), Arg
+ .endmacro
</verb></tscreen>
load instructions, the '#' token has to get stripped from the argument:
<tscreen><verb>
- .macro ldax arg
- .if (.match (.mid (0, 1, {arg}), #))
- ; ldax called with immediate operand
- lda #<(.right (.tcount ({arg})-1, {arg}))
- ldx #>(.right (.tcount ({arg})-1, {arg}))
- .else
- ...
- .endif
- .endmacro
+ .macro ldax arg
+ .if (.match (.mid (0, 1, {arg}), #))
+ ; ldax called with immediate operand
+ lda #<(.right (.tcount ({arg})-1, {arg}))
+ ldx #>(.right (.tcount ({arg})-1, {arg}))
+ .else
+ ...
+ .endif
+ .endmacro
</verb></tscreen>
The syntax is
<tscreen><verb>
- .XMATCH(<token list #1>, <token list #2>)
+ .XMATCH(<token list #1>, <token list #2>)
</verb></tscreen>
Both token list may contain arbitrary tokens with the exception of the
Example:
<tscreen><verb>
- .addr $0D00, $AF13, _Clear
+ .addr $0D00, $AF13, _Clear
</verb></tscreen>
See: <tt><ref id=".FARADDR" name=".FARADDR"></tt>, <tt><ref id=".WORD"
Example:
<tscreen><verb>
- .align 256
+ .align 256
</verb></tscreen>
Some unexpected behaviour might occur if there are multiple <tt/.ALIGN/
Example:
<tscreen><verb>
- Msg: .asciiz "Hello world"
+ Msg: .asciiz "Hello world"
</verb></tscreen>
This will put the string "Hello world" followed by a binary zero into
Example:
<tscreen><verb>
- .assert * = $8000, error, "Code not at $8000"
+ .assert * = $8000, error, "Code not at $8000"
</verb></tscreen>
The example assertion will check that the current location is at $8000,
Example:
<tscreen><verb>
- .autoimport + ; Switch on auto import
+ .autoimport + ; Switch on auto import
</verb></tscreen>
<sect1><tt>.BANKBYTES</tt><label id=".BANKBYTES"><p>
<tscreen><verb>
.define MyTable TableItem0, TableItem1, TableItem2, TableItem3
- TableLookupLo: .lobytes MyTable
- TableLookupHi: .hibytes MyTable
- TableLookupBank: .bankbytes MyTable
+ TableLookupLo: .lobytes MyTable
+ TableLookupHi: .hibytes MyTable
+ TableLookupBank: .bankbytes MyTable
</verb></tscreen>
which is equivalent to
<tscreen><verb>
TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3
- TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
- TableLookupBank: .byte ^TableItem0, ^TableItem1, ^TableItem2, ^TableItem3
+ TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
+ TableLookupBank: .byte ^TableItem0, ^TableItem1, ^TableItem2, ^TableItem3
</verb></tscreen>
See also: <tt><ref id=".BYTE" name=".BYTE"></tt>,
so this is a shortcut for
<tscreen><verb>
- .segment "BSS"
+ .segment "BSS"
</verb></tscreen>
See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command.
Example:
<tscreen><verb>
- .byte "Hello "
- .byt "world", $0D, $00
+ .byte "Hello "
+ .byt "world", $0D, $00
</verb></tscreen>
Example:
<tscreen><verb>
- .case - ; Identifiers are not case sensitive
+ .case - ; Identifiers are not case sensitive
</verb></tscreen>
"CODE", so this is a shortcut for
<tscreen><verb>
- .segment "CODE"
+ .segment "CODE"
</verb></tscreen>
See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command.
Example:
<tscreen><verb>
- .condes ModuleInit, constructor
- .condes ModInit, 0, 16
+ .condes ModuleInit, constructor
+ .condes ModInit, 0, 16
</verb></tscreen>
See the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref
Example:
<tscreen><verb>
- .constructor ModuleInit
- .constructor ModInit, 16
+ .constructor ModuleInit
+ .constructor ModInit, 16
</verb></tscreen>
See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref
"DATA", so this is a shortcut for
<tscreen><verb>
- .segment "DATA"
+ .segment "DATA"
</verb></tscreen>
See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command.
Example:
<tscreen><verb>
- .dbyt $1234, $4512
+ .dbyt $1234, $4512
</verb></tscreen>
This will emit the bytes
<tscreen><verb>
- $12 $34 $45 $12
+ $12 $34 $45 $12
</verb></tscreen>
into the current segment in that order.
Example:
<tscreen><verb>
- .debuginfo + ; Generate debug info
+ .debuginfo + ; Generate debug info
</verb></tscreen>
<tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by
<tscreen><verb>
- .if .defined(a)
+ .if .defined(a)
</verb></tscreen>
adc foo
.endmacro
- .if .definedmacro(add)
+ .if .definedmacro(add)
add #$01
.else
clc
Example:
<tscreen><verb>
- .destructor ModuleDone
- .destructor ModDone, 16
+ .destructor ModuleDone
+ .destructor ModDone, 16
</verb></tscreen>
See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref
Example:
<tscreen><verb>
- .dword $12344512, $12FA489
+ .dword $12344512, $12FA489
</verb></tscreen>
Example:
<tscreen><verb>
- .if foo = 1
- ...
- .elseif bar = 1
- ...
- .else
- .error "Must define foo or bar!"
- .endif
+ .if foo = 1
+ ...
+ .elseif bar = 1
+ ...
+ .else
+ .error "Must define foo or bar!"
+ .endif
</verb></tscreen>
See also: <tt><ref id=".FATAL" name=".FATAL"></tt>,
Examples:
<tscreen><verb>
- .export foo
+ .export foo
.export bar: far
.export foobar: far = foo * bar
.export baz := foobar, zap: far = baz - bar
Examples:
<tscreen><verb>
- .exportzp foo, bar
+ .exportzp foo, bar
.exportzp baz := $02
</verb></tscreen>
Example:
<tscreen><verb>
- .faraddr DrawCircle, DrawRectangle, DrawHexagon
+ .faraddr DrawCircle, DrawRectangle, DrawHexagon
</verb></tscreen>
See: <tt><ref id=".ADDR" name=".ADDR"></tt>
Example:
<tscreen><verb>
- .if foo = 1
- ...
- .elseif bar = 1
- ...
- .else
- .fatal "Must define foo or bar!"
- .endif
+ .if foo = 1
+ ...
+ .elseif bar = 1
+ ...
+ .else
+ .fatal "Must define foo or bar!"
+ .endif
</verb></tscreen>
See also: <tt><ref id=".ERROR" name=".ERROR"></tt>,
enabled it, so using
<tscreen><verb>
- .FEATURE xxx
+ .FEATURE xxx
</verb></tscreen>
will enable the feature until end of assembly is reached.
<tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag>
- Accept the at character (`@') as a valid character in identifiers. The
+ Accept the at character ('@') as a valid character in identifiers. The
at character is not allowed to start an identifier, even with this
feature enabled.
<tag><tt>dollar_in_identifiers</tt><label id="dollar_in_identifiers"></tag>
- Accept the dollar sign (`$') as a valid character in identifiers. The
+ Accept the dollar sign ('$') as a valid character in identifiers. The
dollar character is not allowed to start an identifier, even with this
feature enabled.
<tag><tt>dollar_is_pc</tt><label id="dollar_is_pc"></tag>
- The dollar sign may be used as an alias for the star (`*'), which
+ The dollar sign may be used as an alias for the star ('*'), which
gives the value of the current PC in expressions.
Note: Assignment to the pseudo variable is not allowed.
<tag><tt>leading_dot_in_identifiers</tt><label id="leading_dot_in_identifiers"></tag>
- Accept the dot (`.') as the first character of an identifier. This may be
+ Accept the dot ('.') as the first character of an identifier. This may be
used for example to create macro names that start with a dot emulating
control directives of other assemblers. Note however, that none of the
reserved keywords built into the assembler, that starts with a dot, may be
<tag><tt>pc_assignment</tt><label id="pc_assignment"></tag>
- Allow assignments to the PC symbol (`*' or `$' if <tt/dollar_is_pc/
+ Allow assignments to the PC symbol ('*' or '$' if <tt/dollar_is_pc/
is enabled). Such an assignment is handled identical to the <tt><ref
id=".ORG" name=".ORG"></tt> command (which is usually not needed, so just
removing the lines with the assignments may also be an option when porting
code written for older assemblers).
+ <tag><tt>string_escapes</tt><label id="string_escapes"></tag>
+
+ Allow C-style backslash escapes within string constants to embed
+ special characters. The following escapes are accepted:
+ <itemize>
+ <item><tt>\\</tt> backslash (<tt>$5C</tt>)
+ <item><tt>\'</tt> single quote (<tt>$27</tt>)
+ <item><tt>\"</tt> double quote (<tt>$22</tt>)
+ <item><tt>\t</tt> tab (<tt>$09</tt>)
+ <item><tt>\r</tt> carriage return (<tt>$0D</tt>)
+ <item><tt>\n</tt> newline (<tt>$0A</tt>)
+ <item><tt>\xNN</tt> (<tt>$NN</tt>)
+ </itemize>
+
+ Note that string escapes are converted to platform-specific characters in
+ the same way that other characters are converted.
+
<tag><tt>ubiquitous_idents</tt><label id="ubiquitous_idents"></tag>
Allow the use of instructions names as names for macros and symbols. This
assembler, the features
<verb>
- labels_without_colons, pc_assignment, loose_char_term
+ labels_without_colons, pc_assignment, loose_char_term
</verb>
may be helpful. They do not make ca65 completely compatible, so you may not
The command is followed by one of the keywords
<tscreen><verb>
- author
- comment
- compiler
+ author
+ comment
+ compiler
</verb></tscreen>
a comma and a string. The option is written into the object file
Examples:
<tscreen><verb>
- .fileopt comment, "Code stolen from my brother"
- .fileopt compiler, "BASIC 2.0"
- .fopt author, "J. R. User"
+ .fileopt comment, "Code stolen from my brother"
+ .fileopt compiler, "BASIC 2.0"
+ .fopt author, "J. R. User"
</verb></tscreen>
Example:
<tscreen><verb>
- .forceimport needthisone, needthistoo
+ .forceimport needthisone, needthistoo
</verb></tscreen>
See: <tt><ref id=".IMPORT" name=".IMPORT"></tt>
Example:
<tscreen><verb>
- .global foo, bar
+ .global foo, bar
</verb></tscreen>
Example:
<tscreen><verb>
- .globalzp foo, bar
+ .globalzp foo, bar
</verb></tscreen>
<sect1><tt>.HIBYTES</tt><label id=".HIBYTES"><p>
<tscreen><verb>
.lobytes $1234, $2345, $3456, $4567
- .hibytes $fedc, $edcb, $dcba, $cba9
+ .hibytes $fedc, $edcb, $dcba, $cba9
</verb></tscreen>
which is equivalent to
<tscreen><verb>
.byte $34, $45, $56, $67
- .byte $fe, $ed, $dc, $cb
+ .byte $fe, $ed, $dc, $cb
</verb></tscreen>
Example:
<tscreen><verb>
.define MyTable TableItem0, TableItem1, TableItem2, TableItem3
- TableLookupLo: .lobytes MyTable
- TableLookupHi: .hibytes MyTable
+ TableLookupLo: .lobytes MyTable
+ TableLookupHi: .hibytes MyTable
</verb></tscreen>
which is equivalent to
<tscreen><verb>
TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3
- TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
+ TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
</verb></tscreen>
See also: <tt><ref id=".BYTE" name=".BYTE"></tt>,
Example:
<tscreen><verb>
- .macro arg1, arg2
- .ifblank arg2
- lda #arg1
- .else
- lda #arg2
- .endif
- .endmacro
+ .macro arg1, arg2
+ .ifblank arg2
+ lda #arg1
+ .else
+ lda #arg2
+ .endif
+ .endmacro
</verb></tscreen>
See also: <tt><ref id=".BLANK" name=".BLANK"></tt>
Example:
<tscreen><verb>
- .macro arg1, arg2
- lda #arg1
- .ifnblank arg2
- lda #arg2
- .endif
- .endmacro
+ .macro arg1, arg2
+ lda #arg1
+ .ifnblank arg2
+ lda #arg2
+ .endif
+ .endmacro
</verb></tscreen>
See also: <tt><ref id=".BLANK" name=".BLANK"></tt>
Example:
<tscreen><verb>
- .ifref ToHex ; If someone used this subroutine
- ToHex: tay ; Define subroutine
- lda HexTab,y
- rts
- .endif
+ .ifref ToHex ; If someone used this subroutine
+ ToHex: tay ; Define subroutine
+ lda HexTab,y
+ rts
+ .endif
</verb></tscreen>
See also: <tt><ref id=".REFERENCED" name=".REFERENCED"></tt>
Example:
<tscreen><verb>
- .import foo
+ .import foo
.import bar: zeropage
</verb></tscreen>
Example:
<tscreen><verb>
- .importzp foo, bar
+ .importzp foo, bar
</verb></tscreen>
See: <tt><ref id=".IMPORT" name=".IMPORT"></tt>
Example:
<tscreen><verb>
- ; Include whole file
- .incbin "sprites.dat"
+ ; Include whole file
+ .incbin "sprites.dat"
- ; Include file starting at offset 256
- .incbin "music.dat", $100
+ ; Include file starting at offset 256
+ .incbin "music.dat", $100
- ; Read 100 bytes starting at offset 200
- .incbin "graphics.dat", 200, 100
+ ; Read 100 bytes starting at offset 200
+ .incbin "graphics.dat", 200, 100
</verb></tscreen>
Example:
<tscreen><verb>
- .include "subs.inc"
+ .include "subs.inc"
</verb></tscreen>
Example:
<tscreen><verb>
- .interruptor IrqHandler
- .interruptor Handler, 16
+ .interruptor IrqHandler
+ .interruptor Handler, 16
</verb></tscreen>
See the <tt><ref id=".CONDES" name=".CONDES"></tt> command and the separate
Example:
<tscreen><verb>
- .if .not .ismnemonic(ina)
- .macro ina
- clc
- adc #$01
- .endmacro
- .endif
+ .if .not .ismnemonic(ina)
+ .macro ina
+ clc
+ adc #$01
+ .endmacro
+ .endif
</verb></tscreen>
Example:
<tscreen><verb>
- .linecont + ; Allow line continuations
+ .linecont + ; Allow line continuations
- lda \
- #$20 ; This is legal now
+ lda \
+ #$20 ; This is legal now
</verb></tscreen>
Example:
<tscreen><verb>
- .list on ; Enable listing output
+ .list on ; Enable listing output
</verb></tscreen>
Examples:
<tscreen><verb>
- .listbytes unlimited ; List all bytes
- .listbytes 12 ; List the first 12 bytes
- .incbin "data.bin" ; Include large binary file
+ .listbytes unlimited ; List all bytes
+ .listbytes 12 ; List the first 12 bytes
+ .incbin "data.bin" ; Include large binary file
</verb></tscreen>
<tscreen><verb>
.lobytes $1234, $2345, $3456, $4567
- .hibytes $fedc, $edcb, $dcba, $cba9
+ .hibytes $fedc, $edcb, $dcba, $cba9
</verb></tscreen>
which is equivalent to
<tscreen><verb>
.byte $34, $45, $56, $67
- .byte $fe, $ed, $dc, $cb
+ .byte $fe, $ed, $dc, $cb
</verb></tscreen>
Example:
<tscreen><verb>
.define MyTable TableItem0, TableItem1, TableItem2, TableItem3
- TableLookupLo: .lobytes MyTable
- TableLookupHi: .hibytes MyTable
+ TableLookupLo: .lobytes MyTable
+ TableLookupHi: .hibytes MyTable
</verb></tscreen>
which is equivalent to
<tscreen><verb>
TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3
- TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
+ TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3
</verb></tscreen>
See also: <tt><ref id=".BYTE" name=".BYTE"></tt>,
Example:
<tscreen><verb>
- .localchar '?'
-
- Clear: lda #$00 ; Global label
- ?Loop: sta Mem,y ; Local label
- dey
- bne ?Loop ; Ok
- rts
- Sub: ... ; New global label
- bne ?Loop ; ERROR: Unknown identifier!
+ .localchar '?'
+
+ Clear: lda #$00 ; Global label
+ ?Loop: sta Mem,y ; Local label
+ dey
+ bne ?Loop ; Ok
+ rts
+ Sub: ... ; New global label
+ bne ?Loop ; ERROR: Unknown identifier!
</verb></tscreen>
Example:
<tscreen><verb>
- .macpack longbranch ; Include macro package
+ .macpack longbranch ; Include macro package
- cmp #$20 ; Set condition codes
- jne Label ; Jump long on condition
+ cmp #$20 ; Set condition codes
+ jne Label ; Jump long on condition
</verb></tscreen>
Macro packages are explained in more detail in section <ref
Example:
<tscreen><verb>
- .macro ldax arg ; Define macro ldax
+ .macro ldax arg ; Define macro ldax
lda arg
ldx arg+1
</verb></tscreen>
Example:
<tscreen><verb>
- .org $7FF ; Emit code starting at $7FF
+ .org $7FF ; Emit code starting at $7FF
</verb></tscreen>
Example:
<tscreen><verb>
- .out "This code was written by the codebuster(tm)"
+ .out "This code was written by the codebuster(tm)"
</verb></tscreen>
See also: <tt><ref id=".ERROR" name=".ERROR"></tt>,
Examples:
<tscreen><verb>
- .pagelength 66 ; Use 66 lines per listing page
+ .pagelength 66 ; Use 66 lines per listing page
- .pagelength unlimited ; Unlimited page length
+ .pagelength unlimited ; Unlimited page length
</verb></tscreen>
Example:
<tscreen><verb>
- .proc Clear ; Define Clear subroutine, start new level
- lda #$00
- L1: sta Mem,y ; L1 is local and does not cause a
- ; duplicate symbol error if used in other
- ; places
- dey
- bne L1 ; Reference local symbol
- rts
- .endproc ; Leave lexical level
+ .proc Clear ; Define Clear subroutine, start new level
+ lda #$00
+ L1: sta Mem,y ; L1 is local and does not cause a
+ ; duplicate symbol error if used in other
+ ; places
+ dey
+ bne L1 ; Reference local symbol
+ rts
+ .endproc ; Leave lexical level
</verb></tscreen>
See: <tt/<ref id=".ENDPROC" name=".ENDPROC">/ and <tt/<ref id=".SCOPE"
characters of the string are XORed by the value $55.
<tscreen><verb>
- .macro Crypt Arg
- .repeat .strlen(Arg), I
- .byte .strat(Arg, I) ^ $55
- .endrep
- .endmacro
+ .macro Crypt Arg
+ .repeat .strlen(Arg), I
+ .byte .strat(Arg, I) ^ $55
+ .endrep
+ .endmacro
</verb></tscreen>
See: <tt><ref id=".ENDREPEAT" name=".ENDREPEAT"></tt>
Example:
<tscreen><verb>
- ; Reserve 12 bytes of memory with value $AA
- .res 12, $AA
+ ; Reserve 12 bytes of memory with value $AA
+ .res 12, $AA
</verb></tscreen>
"RODATA", so this is a shortcut for
<tscreen><verb>
- .segment "RODATA"
+ .segment "RODATA"
</verb></tscreen>
The RODATA segment is a segment that is used by the compiler for
Example:
<tscreen><verb>
- .scope Error ; Start new scope named Error
+ .scope Error ; Start new scope named Error
None = 0 ; No error
File = 1 ; File error
Parse = 2 ; Parse error
- .endscope ; Close lexical level
+ .endscope ; Close lexical level
...
lda #Error::File ; Use symbol from scope Error
page and direct (short) addressing is possible for data in this segment.
Beware: Only labels in a segment with the zeropage attribute are marked
- as reachable by short addressing. The `*' (PC counter) operator will
+ as reachable by short addressing. The '*' (PC counter) operator will
work as in other segments and will create absolute variable values.
Please note that a segment cannot have two different address sizes. A
Examples:
<tscreen><verb>
- .segment "ROM2" ; Switch to ROM2 segment
- .segment "ZP2": zeropage ; New direct segment
- .segment "ZP2" ; Ok, will use last attribute
- .segment "ZP2": absolute ; Error, redecl mismatch
+ .segment "ROM2" ; Switch to ROM2 segment
+ .segment "ZP2": zeropage ; New direct segment
+ .segment "ZP2" ; Ok, will use last attribute
+ .segment "ZP2": absolute ; Error, redecl mismatch
</verb></tscreen>
See: <tt><ref id=".BSS" name=".BSS"></tt>, <tt><ref id=".CODE"
Example:
<tscreen><verb>
- .smart ; Be smart
- .smart - ; Stop being smart
+ .smart ; Be smart
+ .smart - ; Stop being smart
</verb></tscreen>
See: <tt><ref id=".A16" name=".A16"></tt>,
Example:
<tscreen><verb>
- .macro jne target
- .local L1
- .ifndef target
- .warning "Forward jump in jne, cannot optimize!"
- beq L1
- jmp target
- L1:
- .else
- ...
- .endif
- .endmacro
+ .macro jne target
+ .local L1
+ .ifndef target
+ .warning "Forward jump in jne, cannot optimize!"
+ beq L1
+ jmp target
+ L1:
+ .else
+ ...
+ .endif
+ .endmacro
</verb></tscreen>
See also: <tt><ref id=".ERROR" name=".ERROR"></tt>,
Example:
<tscreen><verb>
- .word $0D00, $AF13, _Clear
+ .word $0D00, $AF13, _Clear
</verb></tscreen>
<itemize>
-<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> may not
- span more than a line. You may use line continuation (see <tt><ref
- id=".LINECONT" name=".LINECONT"></tt>) to spread the definition over
- more than one line for increased readability, but the macro itself
- may not contain an end-of-line token.
-
-<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> share
- the name space with classic macros, but they are detected and replaced
- at the scanner level. While classic macros may be used in every place,
- where a mnemonic or other directive is allowed, <tt><ref id=".DEFINE"
- name=".DEFINE"></tt> style macros are allowed anywhere in a line. So
- they are more versatile in some situations.
-
-<item> <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may take
- parameters. While classic macros may have empty parameters, this is
- not true for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros.
- For this macro type, the number of actual parameters must match
- exactly the number of formal parameters.
-
- To make this possible, formal parameters are enclosed in braces when
- defining the macro. If there are no parameters, the empty braces may
- be omitted.
-
-<item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not
- contain end-of-line tokens, there are things that cannot be done. They
- may not contain several processor instructions for example. So, while
- some things may be done with both macro types, each type has special
- usages. The types complement each other.
+<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> may not
+ span more than a line. You may use line continuation (see <tt><ref
+ id=".LINECONT" name=".LINECONT"></tt>) to spread the definition over
+ more than one line for increased readability, but the macro itself
+ may not contain an end-of-line token.
+
+<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> share
+ the name space with classic macros, but they are detected and replaced
+ at the scanner level. While classic macros may be used in every place,
+ where a mnemonic or other directive is allowed, <tt><ref id=".DEFINE"
+ name=".DEFINE"></tt> style macros are allowed anywhere in a line. So
+ they are more versatile in some situations.
+
+<item> <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may take
+ parameters. While classic macros may have empty parameters, this is
+ not true for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros.
+ For this macro type, the number of actual parameters must match
+ exactly the number of formal parameters.
+
+ To make this possible, formal parameters are enclosed in braces when
+ defining the macro. If there are no parameters, the empty braces may
+ be omitted.
+
+<item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not
+ contain end-of-line tokens, there are things that cannot be done. They
+ may not contain several processor instructions for example. So, while
+ some things may be done with both macro types, each type has special
+ usages. The types complement each other.
+
+<item> Parentheses work differently from C macros.
+ The common practice of wrapping C macros in parentheses may cause
+ unintended problems here, such as accidentally implying an
+ indirect addressing mode. While the definition of a macro requires
+ parentheses around its argument list, when invoked they should not be
+ included.
</itemize>
DEBUG "Assembling include file #3"
</verb></tscreen>
-Note that, while formal parameters have to be placed in braces, this is
-not true for the actual parameters. Beware: Since the assembler cannot
-detect the end of one parameter, only the first token is used. If you
-don't like that, use classic macros instead:
+Note that, while formal parameters have to be placed in parentheses,
+the actual argument used when invoking the macro should not be.
+The invoked arguments are separated by commas only, if parentheses are
+used by accident they will become part of the replaced token.
+
+If you wish to have an expression follow the macro invocation, the
+last parameter can be enclosed in curly braces {} to indicate the end of that
+argument.
+
+Examples:
<tscreen><verb>
-.macro DEBUG message
- .out message
-.endmacro
+.define COMBINE(ta,tb,tc) ta+tb*10+tc*100
+
+.word COMBINE 5,6,7 ; 5+6*10+7*100 = 765
+.word COMBINE(5,6,7) ; (5+6*10+7)*100 = 7200 ; incorrect use of parentheses
+.word COMBINE 5,6,7+1 ; 5+6*10+7+1*100 = 172
+.word COMBINE 5,6,{7}+1 ; 5+6*10+7*100+1 = 766 ; {} encloses the argument
+.word COMBINE 5,6-2,7 ; 5+6-2*10+7*100 = 691
+.word COMBINE 5,(6-2),7 ; 5+(6-2)*10+7*100 = 745
+.word COMBINE 5,6,7+COMBINE 0,1,2 ; 5+6*10+7+0+1*10+2*100*100 = 20082
+.word COMBINE 5,6,{7}+COMBINE 0,1,2 ; 5+6*10+7*100+0+1*10+2*100 = 975
</verb></tscreen>
-(That is an example where a problem can be solved with both macro types).
+With C macros it is common to enclose the results in parentheses to
+prevent unintended interactions with the text of the arguments, but
+additional care must be taken in this assembly context where parentheses
+may alter the meaning of a statement. In particular, indirect addressing modes
+may be accidentally implied:
+
+<tscreen><verb>
+.define DUO(ta,tb) (ta+(tb*10))
+
+ lda DUO(5,4), Y ; LDA (indirect), Y
+ lda 0+DUO(5,4), Y ; LDA absolute indexed, Y
+</verb></tscreen>
<sect1>Characters in macros<p>
<tscreen><verb>
.macro add Arg ; add without carry
- clc
- adc Arg
- .endmacro
+ clc
+ adc Arg
+ .endmacro
.macro sub Arg ; subtract without borrow
- sec
- sbc Arg
- .endmacro
+ sec
+ sbc Arg
+ .endmacro
.macro bge Arg ; branch on greater-than or equal
bcs Arg
scheme:
<tscreen><verb>
- .macro jeq Target
- .if .def(Target) .and ((*+2)-(Target) <= 127)
- beq Target
- .else
- bne *+5
- jmp Target
- .endif
- .endmacro
+ .macro jeq Target
+ .if .def(Target) .and ((*+2)-(Target) <= 127)
+ beq Target
+ .else
+ bne *+5
+ jmp Target
+ .endif
+ .endmacro
</verb></tscreen>
All macros expand to a short branch, if the label is already defined (back
The package defines the following macros:
<tscreen><verb>
- jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc
+ jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc
</verb></tscreen>
freely, subject to the following restrictions:
<enum>
-<item> The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-<item> Altered source versions must be plainly marked as such, and must not
- be misrepresented as being the original software.
-<item> This notice may not be removed or altered from any source
- distribution.
+<item> The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+<item> Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+<item> This notice may not be removed or altered from any source
+ distribution.
</enum>