<article>
<title>ca65 Users Guide
-<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
-<date>2014-04-24
+<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
+ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is
used as a companion assembler for the cc65 crosscompiler, but it may also be
used as a standalone product.
</abstract>
Set the default for the CPU type. The option takes a parameter, which
may be one of
- 6502, 65SC02, 65C02, 65816, sweet16, HuC6280
+ 6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
<label id="option-create-dep">
<tt><ref id=".PSC02" name=".PSC02"></tt> command was given).
<item>all valid 65C02 mnemonics when in 65C02 mode (after the
<tt><ref id=".PC02" name=".PC02"></tt> command was given).
-<item>all valid 65618 mnemonics when in 65816 mode (after the
+<item>all valid 65816 mnemonics when in 65816 mode (after the
<tt><ref id=".P816" name=".P816"></tt> command was given).
+<item>all valid 4510 mnemonics when in 4510 mode (after the
+ <tt><ref id=".P4510" name=".P4510"></tt> command was given).
</itemize>
<sect1>65816 mode<p>
-In 65816 mode several aliases are accepted in addition to the official
+In 65816 mode, several aliases are accepted, in addition to the official
mnemonics:
-<tscreen><verb>
- BGE is an alias for BCS
- BLT is an alias for BCC
- CPA is an alias for CMP
- DEA is an alias for DEC A
- INA is an alias for INC A
- SWA is an alias for XBA
- TAD is an alias for TCD
- TAS is an alias for TCS
- TDA is an alias for TDC
- TSA is an alias for TSC
-</verb></tscreen>
-
+<itemize>
+<item><tt>CPA</tt> is an alias for <tt>CMP</tt>
+<item><tt>DEA</tt> is an alias for <tt>DEC A</tt>
+<item><tt>INA</tt> is an alias for <tt>INC A</tt>
+<item><tt>SWA</tt> is an alias for <tt>XBA</tt>
+<item><tt>TAD</tt> is an alias for <tt>TCD</tt>
+<item><tt>TAS</tt> is an alias for <tt>TCS</tt>
+<item><tt>TDA</tt> is an alias for <tt>TDC</tt>
+<item><tt>TSA</tt> is an alias for <tt>TSC</tt>
+</itemize>
<sect1>6502X mode<label id="6502X-mode"><p>
</itemize>
+<sect1>4510 mode<p>
+
+The 4510 is a microcontroller that is the core of the Commodore C65 aka C64DX.
+It contains among other functions a slightly modified 65CE02/4502 CPU, to allow
+address mapping for 20 bits of address space (1 megabyte addressable area).
+As compared to the description of the CPU in the
+<url url="http://www.zimmers.net/anonftp/pub/cbm/c65/c65manualupdated.txt.gz"
+name="C65 System Specification">
+<url url="https://raw.githubusercontent.com/MEGA65/c65-specifications/master/c65manualupdated.txt"
+name="(updated version)"> uses these changes:
+<itemize>
+<item><tt>LDA (d,SP),Y</tt> may also be written as <tt>LDA (d,S),Y</tt>
+(matching the 65816 notataion).
+<item>All branch instruction allow now 16 bit offsets. To use a 16 bit
+branch you have to prefix these with an "L" (e.g. "<tt>LBNE</tt>" instead of
+"<tt>BNE</tt>"). This might change at a later implementation of the assembler.
+</itemize>
+For more information about the Commodore C65/C64DX and the 4510 CPU, see
+<url url="http://www.zimmers.net/anonftp/pub/cbm/c65/"> and
+<url url="https://en.wikipedia.org/wiki/Commodore_65" name="Wikipedia">.
+
<sect1>sweet16 mode<label id="sweet16-mode"><p>
assignments to <tt/*/, use <tt/<ref id=".ORG" name=".ORG">/ instead.
+<sect1><tt>.ASIZE</tt><label id=".ASIZE"><p>
+
+ Reading this pseudo variable will return the current size of the
+ Accumulator in bits.
+
+ For the 65816 instruction set .ASIZE will return either 8 or 16, depending
+ on the current size of the operand in immediate accu addressing mode.
+
+ For all other CPU instruction sets, .ASIZE will always return 8.
+
+ 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
+ </verb></tscreen>
+
+ See also: <tt><ref id=".ISIZE" name=".ISIZE"></tt>
+
+
<sect1><tt>.CPU</tt><label id=".CPU"><p>
Reading this pseudo variable will give a constant integer value that
</verb></tscreen>
+<sect1><tt>.ISIZE</tt><label id=".ISIZE"><p>
+
+ Reading this pseudo variable will return the current size of the Index
+ register in bits.
+
+ For the 65816 instruction set .ISIZE will return either 8 or 16, depending
+ on the current size of the operand in immediate index addressing mode.
+
+ For all other CPU instruction sets, .ISIZE will always return 8.
+
+ See also: <tt><ref id=".ASIZE" name=".ASIZE"></tt>
+
+
<sect1><tt>.PARAMCOUNT</tt><label id=".PARAMCOUNT"><p>
This builtin pseudo variable is only available in macros. It is replaced by
<sect1><tt>.ADDRSIZE</tt><label id=".ADDRSIZE"><p>
- The <tt/.ADDRSIZE/ function is used to return the interal address size
- associated with a symbol. This can be helpful in macros when knowing the address
+ The <tt/.ADDRSIZE/ function is used to return the interal address size
+ associated with a symbol. This can be helpful in macros when knowing the address
size of symbol can help with custom instructions.
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>
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>
<sect1><tt>.CHARMAP</tt><label id=".CHARMAP"><p>
Apply a custom mapping for characters. The command is followed by two
- numbers. The first one is the index of the source character (range 1..255),
+ numbers. The first one is the index of the source character (range 0..255);
the second one is the mapping (range 0..255). The mapping applies to all
- character and string constants when they generate output, and overrides a
- mapping table specified with the <tt><ref id="option-t" name="-t"></tt>
+ character and string constants <em/when/ they generate output; and, overrides
+ a mapping table specified with the <tt><ref id="option-t" name="-t"></tt>
command line switch.
Example:
-
<tscreen><verb>
- .charmap $41, $61 ; Map 'A' to 'a'
+ .charmap $41, $61 ; Map 'A' to 'a'
</verb></tscreen>
</verb></tscreen>
-<sect1><tt>.DEFINEDINSTR</tt><label id=".DEFINEDINSTR"><p>
+<sect1><tt>.DEFINEDMACRO</tt><label id=".DEFINEDMACRO"><p>
Builtin function. The function expects an identifier as argument in braces.
The argument is evaluated, and the function yields "true" if the identifier
- is defined as an instruction mnemonic that is recognized by the assembler.
- Example:
+ has already been defined as the name of a macro. Otherwise the function yields
+ false. Example:
<tscreen><verb>
- .if .not .definedinstr(ina)
- .macro ina
- clc
- adc #$01
- .endmacro
- .endif
+ .macro add foo
+ clc
+ adc foo
+ .endmacro
+ .if .definedmacro(add)
+ add #$01
+ .else
+ clc
+ adc #$01
+ .endif
</verb></tscreen>
at character is not allowed to start an identifier, even with this
feature enabled.
+ <tag><tt>bracket_as_indirect</tt><label id="bracket_as_indirect"></tag>
+
+ Use <tt>[]</tt> instead of <tt>()</tt> for the indirect addressing modes.
+ Example:
+
+ <tscreen><verb>
+ lda [$82]
+ lda [$82,x]
+ lda [$82],y
+ jmp [$fffe]
+ jmp [table,x]
+ </verb></tscreen>
+ <em/Note:/ This should not be used in 65186 mode because it conflicts with
+ the 65816 instruction syntax for far addressing. See the section covering
+ <tt/<ref id="address-sizes" name="address sizes">/ for more information.
+
<tag><tt>c_comments</tt><label id="c_comments"></tag>
Allow C like comments using <tt>/*</tt> and <tt>*/</tt> as left and right
Conditional assembly: Check if there are any remaining tokens in this line,
and evaluate to FALSE if this is the case, and to TRUE otherwise. If the
condition is not true, further lines are not assembled until an <tt><ref
- id=".ELSE" name=".ESLE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or
+ id=".ELSE" name=".ELSE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or
<tt><ref id=".ENDIF" name=".ENDIF"></tt> directive.
This command is often used to check if a macro parameter was given. Since an
(see <tt><ref id=".P02" name=".P02"></tt> command).
+<sect1><tt>.IFP4510</tt><label id=".IFP4510"><p>
+
+ Conditional assembly: Check if the assembler is currently in 4510 mode
+ (see <tt><ref id=".P4510" name=".P4510"></tt> command).
+
+
<sect1><tt>.IFP816</tt><label id=".IFP816"><p>
Conditional assembly: Check if the assembler is currently in 65816 mode
the feature in more detail.
+<sect1><tt>.ISMNEM, .ISMNEMONIC</tt><label id=".ISMNEMONIC"><p>
+
+ Builtin function. The function expects an identifier as argument in braces.
+ The argument is evaluated, and the function yields "true" if the identifier
+ is defined as an instruction mnemonic that is recognized by the assembler.
+ Example:
+
+ <tscreen><verb>
+ .if .not .ismnemonic(ina)
+ .macro ina
+ clc
+ adc #$01
+ .endmacro
+ .endif
+ </verb></tscreen>
+
+
<sect1><tt>.LINECONT</tt><label id=".LINECONT"><p>
Switch on or off line continuations using the backslash character
atari Defines the scrcode macro.
cbm Defines the scrcode macro.
cpu Defines constants for the .CPU variable.
- generic Defines generic macros like add and sub.
- longbranch Defines conditional long jump macros.
+ generic Defines generic macroes like add, sub, and blt.
+ longbranch Defines conditional long-jump macroes.
</verb></tscreen>
Including a macro package twice, or including a macro package that
<tt><ref id="option--cpu" name="--cpu"></tt> command line option.
See: <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
+
+
+<sect1><tt>.P4510</tt><label id=".P4510"><p>
+
+ Enable the 4510 instruction set. This is a superset of the 65C02 and
+ 6502 instruction sets.
+
+ See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
+ name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and
+ <tt><ref id=".P816" name=".P816"></tt>
<sect1><tt>.P816</tt><label id=".P816"><p>
6502 instruction sets.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".PC02" name=".PC02"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.PAGELEN, .PAGELENGTH</tt><label id=".PAGELENGTH"><p>
6502 and 65SC02 instructions.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.POPCPU</tt><label id=".POPCPU"><p>
6502 instructions.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PC02"
- name=".PC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.PUSHCPU</tt><label id=".PUSHCPU"><p>
segment, that is, a named section of data. The default segment is
"CODE". There may be up to 254 different segments per object file
(and up to 65534 per executable). There are shortcut commands for
- the most common segments ("CODE", "DATA" and "BSS").
+ the most common segments ("ZEROPAGE", "CODE", "RODATA", "DATA", and "BSS").
The command is followed by a string containing the segment name (there are
some constraints for the name - as a rule of thumb use only those segment
</verb></tscreen>
See: <tt><ref id=".BSS" name=".BSS"></tt>, <tt><ref id=".CODE"
- name=".CODE"></tt>, <tt><ref id=".DATA" name=".DATA"></tt> and <tt><ref
- id=".RODATA" name=".RODATA"></tt>
+ name=".CODE"></tt>, <tt><ref id=".DATA" name=".DATA"></tt>, <tt><ref
+ id=".RODATA" name=".RODATA"></tt>, and <tt><ref id=".ZEROPAGE"
+ name=".ZEROPAGE"></tt>
<sect1><tt>.SET</tt><label id=".SET"><p>
Switch the CPU instruction set. The command is followed by a string that
specifies the CPU. Possible values are those that can also be supplied to
the <tt><ref id="option--cpu" name="--cpu"></tt> command line option,
- namely: 6502, 6502X, 65SC02, 65C02, 65816 and HuC6280.
+ namely: 6502, 6502X, 65SC02, 65C02, 65816, 4510 and HuC6280.
See: <tt><ref id=".CPU" name=".CPU"></tt>,
<tt><ref id=".IFP02" name=".IFP02"></tt>,
<tt><ref id=".IFPSC02" name=".IFPSC02"></tt>,
<tt><ref id=".P02" name=".P02"></tt>,
<tt><ref id=".P816" name=".P816"></tt>,
+ <tt><ref id=".P4510" name=".P4510"></tt>,
<tt><ref id=".PC02" name=".PC02"></tt>,
<tt><ref id=".PSC02" name=".PSC02"></tt>
shortcut for
<tscreen><verb>
- .segment "ZEROPAGE", zeropage
+ .segment "ZEROPAGE": zeropage
</verb></tscreen>
Because of the "zeropage" attribute, labels declared in this segment are
example:
<tscreen><verb>
- .macro asr ; Arithmetic shift right
- cmp #$80 ; Put bit 7 into carry
- ror ; Rotate right with carry
- .endmacro
+.macro asr ; Arithmetic shift right
+ cmp #$80 ; Put bit 7 into carry
+ ror ; Rotate right with carry
+.endmacro
</verb></tscreen>
The macro above consists of two real instructions, that are inserted into
by using the name, like this:
<tscreen><verb>
- lda $2010
- asr
- sta $2010
+ lda $2010
+ asr
+ sta $2010
</verb></tscreen>
When using macro parameters, macros can be even more useful:
<tscreen><verb>
- .macro inc16 addr
- clc
- lda addr
- adc #$01
- sta addr
- lda addr+1
- adc #$00
- sta addr+1
- .endmacro
+.macro inc16 addr
+ clc
+ lda addr
+ adc #<$0001
+ sta addr
+ lda addr+1
+ adc #>$0001
+ sta addr+1
+.endmacro
</verb></tscreen>
When calling the macro, you may give a parameter, and each occurrence of
parameter. So
<tscreen><verb>
- inc16 $1000
+ inc16 $1000
</verb></tscreen>
will be expanded to
<tscreen><verb>
- clc
- lda $1000
- adc #$01
- sta $1000
- lda $1000+1
- adc #$00
- sta $1000+1
+ clc
+ lda $1000
+ adc #<$0001
+ sta $1000
+ lda $1000+1
+ adc #>$0001
+ sta $1000+1
</verb></tscreen>
A macro may have more than one parameter, in this case, the parameters
Look at this example:
<tscreen><verb>
- .macro ldaxy a, x, y
- .ifnblank a
- lda #a
- .endif
- .ifnblank x
- ldx #x
- .endif
- .ifnblank y
- ldy #y
- .endif
- .endmacro
+.macro ldaxy a, x, y
+.ifnblank a
+ lda #a
+.endif
+.ifnblank x
+ ldx #x
+.endif
+.ifnblank y
+ ldy #y
+.endif
+.endmacro
</verb></tscreen>
-This macro may be called as follows:
+That macro may be called as follows:
<tscreen><verb>
- ldaxy 1, 2, 3 ; Load all three registers
+ ldaxy 1, 2, 3 ; Load all three registers
- ldaxy 1, , 3 ; Load only a and y
+ ldaxy 1, , 3 ; Load only a and y
- ldaxy , , 3 ; Load y only
+ ldaxy , , 3 ; Load y only
</verb></tscreen>
-There's another helper command for determining, which macro parameters are
-valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt> This command is
-replaced by the parameter count given, <em/including/ intermediate empty macro
+There's another helper command for determining which macro parameters are
+valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>. That command is
+replaced by the parameter count given, <em/including/ explicitly empty
parameters:
<tscreen><verb>
- ldaxy 1 ; .PARAMCOUNT = 1
- ldaxy 1,,3 ; .PARAMCOUNT = 3
- ldaxy 1,2 ; .PARAMCOUNT = 2
- ldaxy 1, ; .PARAMCOUNT = 2
- ldaxy 1,2,3 ; .PARAMCOUNT = 3
+ ldaxy 1 ; .PARAMCOUNT = 1
+ ldaxy 1,,3 ; .PARAMCOUNT = 3
+ ldaxy 1,2 ; .PARAMCOUNT = 2
+ ldaxy 1, ; .PARAMCOUNT = 2
+ ldaxy 1,2,3 ; .PARAMCOUNT = 3
</verb></tscreen>
Macro parameters may optionally be enclosed into curly braces. This allows the
case of a macro parameter).
<tscreen><verb>
- .macro foo arg1, arg2
- ...
- .endmacro
+.macro foo arg1, arg2
+ ...
+.endmacro
- foo ($00,x) ; Two parameters passed
- foo {($00,x)} ; One parameter passed
+ foo ($00,x) ; Two parameters passed
+ foo {($00,x)} ; One parameter passed
</verb></tscreen>
In the first case, the macro is called with two parameters: '<tt/($00/'
-and 'x)'. The comma is not passed to the macro, since it is part of the
+and '<tt/x)/'. The comma is not passed to the macro, because it is part of the
calling sequence, not the parameters.
-In the second case, '($00,x)' is passed to the macro, this time
+In the second case, '<tt/($00,x)/' is passed to the macro; this time,
including the comma.
functions will allow you to do exactly this:
<tscreen><verb>
- .macro ldax arg
- .if (.match (.left (1, {arg}), #))
- ; immediate mode
- lda #<(.right (.tcount ({arg})-1, {arg}))
- ldx #>(.right (.tcount ({arg})-1, {arg}))
- .else
- ; assume absolute or zero page
- lda arg
- ldx 1+(arg)
- .endif
- .endmacro
+.macro ldax arg
+ .if (.match (.left (1, {arg}), #))
+ ; immediate mode
+ lda #<(.right (.tcount ({arg})-1, {arg}))
+ ldx #>(.right (.tcount ({arg})-1, {arg}))
+ .else
+ ; assume absolute or zero page
+ lda arg
+ ldx 1+(arg)
+ .endif
+.endmacro
</verb></tscreen>
Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to
The macro can be used as
<tscreen><verb>
- foo: .word $5678
- ...
- ldax #$1234 ; X=$12, A=$34
- ...
- ldax foo ; X=$56, A=$78
+foo: .word $5678
+...
+ ldax #$1234 ; X=$12, A=$34
+...
+ ldax foo ; X=$56, A=$78
</verb></tscreen>
Macros may be used recursively:
<tscreen><verb>
- .macro push r1, r2, r3
- lda r1
- pha
- .if .paramcount > 1
- push r2, r3
- .endif
- .endmacro
+.macro push r1, r2, r3
+ lda r1
+ pha
+.ifnblank r2
+ push r2, r3
+.endif
+.endmacro
</verb></tscreen>
-There's also a special macro to help writing recursive macros: <tt><ref
-id=".EXITMACRO" name=".EXITMACRO"></tt> This command will stop macro expansion
-immediately:
+There's also a special macro command to help with writing recursive macros:
+<tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>. That command will stop macro
+expansion immediately:
<tscreen><verb>
- .macro push r1, r2, r3, r4, r5, r6, r7
- .ifblank r1
- ; First parameter is empty
- .exitmacro
- .else
- lda r1
- pha
- .endif
- push r2, r3, r4, r5, r6, r7
- .endmacro
+.macro push r1, r2, r3, r4, r5, r6, r7
+.ifblank r1
+ ; First parameter is empty
+ .exitmacro
+.else
+ lda r1
+ pha
+.endif
+ push r2, r3, r4, r5, r6, r7
+.endmacro
</verb></tscreen>
-When expanding this macro, the expansion will push all given parameters
+When expanding that macro, the expansion will push all given parameters
until an empty one is encountered. The macro may be called like this:
<tscreen><verb>
- push $20, $21, $32 ; Push 3 ZP locations
- push $21 ; Push one ZP location
+ push $20, $21, $32 ; Push 3 ZP locations
+ push $21 ; Push one ZP location
</verb></tscreen>
Have a look at the inc16 macro above. Here is it again:
<tscreen><verb>
- .macro inc16 addr
- clc
- lda addr
- adc #$01
- sta addr
- lda addr+1
- adc #$00
- sta addr+1
- .endmacro
+.macro inc16 addr
+ clc
+ lda addr
+ adc #<$0001
+ sta addr
+ lda addr+1
+ adc #>$0001
+ sta addr+1
+.endmacro
</verb></tscreen>
If you have a closer look at the code, you will notice, that it could be
written more efficiently, like this:
<tscreen><verb>
- .macro inc16 addr
- inc addr
- bne Skip
- inc addr+1
- Skip:
- .endmacro
+.macro inc16 addr
+ inc addr
+ bne Skip
+ inc addr+1
+Skip:
+.endmacro
</verb></tscreen>
But imagine what happens, if you use this macro twice? Since the label "Skip"
expansion. So we can solve the problem above by using <tt/.LOCAL/:
<tscreen><verb>
- .macro inc16 addr
- .local Skip ; Make Skip a local symbol
- inc addr
- bne Skip
- inc addr+1
- Skip: ; Not visible outside
- .endmacro
+.macro inc16 addr
+ .local Skip ; Make Skip a local symbol
+ inc addr
+ bne Skip
+ inc addr+1
+Skip: ; Not visible outside
+.endmacro
</verb></tscreen>
Another solution is of course to start a new lexical block inside the macro
that hides any labels:
<tscreen><verb>
- .macro inc16 addr
- .proc
- inc addr
- bne Skip
- inc addr+1
- Skip:
- .endproc
- .endmacro
+.macro inc16 addr
+.proc
+ inc addr
+ bne Skip
+ inc addr+1
+Skip:
+.endproc
+.endmacro
</verb></tscreen>
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
+ 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>
Let's look at a few examples to make the advantages and disadvantages
following <tt/.DEFINE/:
<tscreen><verb>
- .define EQU =
+.define EQU =
- foo EQU $1234 ; This is accepted now
+foo EQU $1234 ; This is accepted now
</verb></tscreen>
You may use the directive to define string constants used elsewhere:
<tscreen><verb>
- ; Define the version number
- .define VERSION "12.3a"
+; Define the version number
+.define VERSION "12.3a"
- ; ... and use it
- .asciiz VERSION
+ ; ... and use it
+ .asciiz VERSION
</verb></tscreen>
Macros with parameters may also be useful:
<tscreen><verb>
- .define DEBUG(message) .out message
+.define DEBUG(message) .out message
- DEBUG "Assembling include file #3"
+ 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>
-(This 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>
<sect1>Deleting macros<p>
Macros can be deleted. This will not work if the macro that should be deleted
-is currently expanded as in the following non working example:
+is currently expanded as in the following non-working example:
<tscreen><verb>
- .macro notworking
- .delmacro notworking
- .endmacro
+.macro notworking
+ .delmacro notworking
+.endmacro
notworking ; Will not work
</verb></tscreen>
id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example:
<tscreen><verb>
- .define value 1
- .macro mac
- .byte 2
- .endmacro
+.define value 1
+.macro mac
+ .byte 2
+.endmacro
- .byte value ; Emit one byte with value 1
- mac ; Emit another byte with value 2
+ .byte value ; Emit one byte with value 1
+ mac ; Emit another byte with value 2
- .undefine value
- .delmacro mac
+.undefine value
+.delmacro mac
- .byte value ; Error: Unknown identifier
- mac ; Error: Missing ":"
+ .byte value ; Error: Unknown identifier
+ mac ; Error: Missing ":"
</verb></tscreen>
A separate command for <tt>.DEFINE</tt> style macros was necessary, because
different commands increases flexibility.
+
<sect>Macro packages<label id="macropackages"><p>
Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined
<sect1><tt>.MACPACK generic</tt><p>
-This macro package defines macros that are useful in almost any program.
-Currently defined macros are:
+This macro package defines macroes that are useful in almost any program.
+Currently defined macroes are:
<tscreen><verb>
- .macro add Arg
+ .macro add Arg ; add without carry
clc
adc Arg
.endmacro
- .macro sub Arg
+ .macro sub Arg ; subtract without borrow
sec
sbc Arg
.endmacro
- .macro bge Arg
+ .macro bge Arg ; branch on greater-than or equal
bcs Arg
.endmacro
- .macro blt Arg
+ .macro blt Arg ; branch on less-than
bcc Arg
.endmacro
- .macro bgt Arg
+ .macro bgt Arg ; branch on greater-than
.local L
beq L
bcs Arg
L:
.endmacro
- .macro ble Arg
+ .macro ble Arg ; branch on less-than or equal
beq Arg
bcc Arg
.endmacro
- .macro bnz Arg
+ .macro bnz Arg ; branch on not zero
bne Arg
.endmacro
- .macro bze Arg
+ .macro bze Arg ; branch on zero
beq Arg
.endmacro
-
</verb></tscreen>
+<sect1><tt>.MACPACK apple2</tt><p>
+
+This macro package defines a macro named <tt/scrcode/. It takes a string
+as argument and places this string into memory translated into screen codes.
+
+
<sect1><tt>.MACPACK atari</tt><p>
This macro package defines a macro named <tt/scrcode/. It takes a string
CPU_65816
CPU_SWEET16
CPU_HUC6280
+ CPU_4510
</verb></tscreen>
is defined. These constants may be used to determine the exact type of the
CPU_ISET_65816
CPU_ISET_SWEET16
CPU_ISET_HUC6280
+ CPU_ISET_4510
</verb></tscreen>
The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may
instruction is supported, which is the case for the 65SC02, 65C02 and 65816
CPUs (the latter two are upwards compatible to the 65SC02).
-
+
<sect1><tt>.MACPACK module</tt><p>
This macro package defines a macro named <tt/module_header/. It takes an
<itemize>
<item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/
<item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/
+<item><tt/__ATARI2600__/ - Target system is <tt/atari2600/
<item><tt/__ATARI5200__/ - Target system is <tt/atari5200/
<item><tt/__ATARI__/ - Target system is <tt/atari/ or <tt/atarixl/
<item><tt/__ATARIXL__/ - Target system is <tt/atarixl/
</article>
-
-
-