mirror of
https://github.com/cc65/cc65.git
synced 2024-08-18 10:29:06 +00:00
2348 lines
69 KiB
Plaintext
2348 lines
69 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
<title>ca65 Users Guide
|
|
<author>Ullrich von Bassewitz, <tt/uz@musoftware.de/
|
|
<date>19.07.2000
|
|
<abstract>ca65 is a macro assembler for the 6502, 65C02 and 65816 CPUs.
|
|
</abstract>
|
|
|
|
<!-- Table of contents -->
|
|
<toc>
|
|
|
|
<!-- Begin the document -->
|
|
|
|
<sect>Overview<p>
|
|
|
|
ca65 is a replacement for the ra65 assembler that was part of the cc65 C
|
|
compiler developed by John R. Dunning. I had some problems with ra65 and
|
|
the copyright does not permit some things which I wanted to be possible,
|
|
so I decided to write a completely new assembler/linker/archiver suite for
|
|
the cc65 compiler. ca65 is part of this suite.
|
|
|
|
Some parts of the assembler (code generation and some routines for symbol
|
|
table handling) are taken from an older crossassembler named a816 written
|
|
by me a long time ago.
|
|
|
|
Here's a list of the design criteria, that were important for the
|
|
development:
|
|
|
|
<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 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. Years ago I
|
|
spent half a day to convince Borlands Turbo Assembler to let me use
|
|
the size of a structure I had created. So I decided that this is a
|
|
must. The linker should be able to get things like
|
|
<tscreen><verb>
|
|
.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.
|
|
</itemize>
|
|
|
|
|
|
<sect>Usage<p>
|
|
|
|
The assembler accepts the following options:
|
|
|
|
<tscreen><verb>
|
|
---------------------------------------------------------------------------
|
|
Usage: ca65 [options] file
|
|
Short options:
|
|
-g Add debug info to object file
|
|
-h Help (this text)
|
|
-i Ignore case of symbols
|
|
-l Create a listing if assembly was ok
|
|
-o name Name the output file
|
|
-s Enable smart mode
|
|
-v Increase verbosity
|
|
-D name[=value] Define a symbol
|
|
-I dir Set an include directory search path
|
|
-U Mark unresolved symbols as import
|
|
-V Print the assembler version
|
|
-W n Set warning level n
|
|
|
|
Long options:
|
|
--auto-import Mark unresolved symbols as import
|
|
--cpu type Set cpu type
|
|
--debug-info Add debug info to object file
|
|
--help Help (this text)
|
|
--ignore-case Ignore case of symbols
|
|
--include-dir dir Set an include directory search path
|
|
--listing Create a listing if assembly was ok
|
|
--pagelength n Set the page length for the listing
|
|
--smart Enable smart mode
|
|
--verbose Increase verbosity
|
|
--version Print the assembler version
|
|
---------------------------------------------------------------------------
|
|
</verb></tscreen>
|
|
|
|
Here is a description of all the command line options:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt>--cpu type</tt></tag>
|
|
|
|
Set the default for the CPU type. The option takes a parameter, which
|
|
may be one of
|
|
|
|
6502, 65C02, 65816 and sunplus
|
|
|
|
(the latter is not available in the freeware version).
|
|
|
|
|
|
<tag><tt>-g, --debug-info</tt></tag>
|
|
|
|
When this option (or the equivalent control command <tt/.DEBUGINFO/) is
|
|
used, the assembler will add a section to the object file that contains
|
|
all symbols (including local ones) together with the symbol values and
|
|
source file positions. The linker will put these additional symbols into
|
|
the VICE label file, so even local symbols can be seen in the VICE
|
|
monitor.
|
|
|
|
|
|
<tag><tt>-h, --help</tt></tag>
|
|
|
|
Print the short option summary shown above.
|
|
|
|
|
|
<tag><tt>-i, --ignore-case</tt></tag>
|
|
|
|
This option makes the assembler case insensitive on identifiers and
|
|
labels. This option will override the default, but may itself be
|
|
overriden by the <tt/.CASE/ control command (see section 6).
|
|
|
|
|
|
<tag><tt>-l, --listing</tt></tag>
|
|
|
|
Generate an assembler listing. The listing file will always have the
|
|
name of the main input file with the extension replaced by ".lst". This
|
|
may change in future versions.
|
|
|
|
|
|
<tag><tt>-o name</tt></tag>
|
|
|
|
The default output name is the name of the input file with the extension
|
|
replaced by ".o". If you don't like that, you may give another name with
|
|
the -o option. The output file will be placed in the same directory as
|
|
the source file, or, if -o is given, the full path in this name is used.
|
|
|
|
|
|
<tag><tt>--pagelength n</tt></tag>
|
|
|
|
sets the length of a listing page in lines. See the <tt/.PAGELENGTH/
|
|
directive for more information.
|
|
|
|
|
|
<tag><tt>-s, --smart-mode</tt></tag>
|
|
|
|
In smart mode (enabled by -s or the <tt/.SMART/ pseudo instruction) the
|
|
assembler will track usage of the REP and SEP instructions in 65816 mode
|
|
and update the operand sizes accordingly. If the operand of such an
|
|
instruction cannot be evaluated by the assembler (for example, because
|
|
the operand is an imported symbol), a warning is issued.
|
|
|
|
Beware: Since the assembler cannot trace the execution flow this may
|
|
lead to false results in some cases. If in doubt, use the .ixx and .axx
|
|
instructions to tell the assembler about the current settings. Smart
|
|
mode is off by default.
|
|
|
|
|
|
<tag><tt>-v, --verbose</tt></tag>
|
|
|
|
Increase the assembler verbosity. Usually only needed for debugging
|
|
purposes. You may use this option more than one time for even more
|
|
verbose output.
|
|
|
|
|
|
<tag><tt>-D</tt></tag>
|
|
|
|
This option allows you to define symbols on the command line. Without a
|
|
value, the symbol is defined with the value zero. When giving a value,
|
|
you may use the '$' prefix for hexadecimal symbols. Please note
|
|
that for some operating systems, '$' has a special meaning, so
|
|
you may have to quote the expression.
|
|
|
|
|
|
<tag><tt>-I dir, --include-dir dir</tt></tag>
|
|
|
|
Name a directory which is searched for include files. The option may be
|
|
used more than once to specify more than one directory to search. The
|
|
current directory is always searched first before considering any
|
|
additional directores.
|
|
|
|
|
|
<tag><tt>-U, --auto-import</tt></tag>
|
|
|
|
Mark symbols that are not defined in the sources as imported symbols.
|
|
This should be used with care since it delays error messages about typos
|
|
and such until the linker is run. The compiler uses the equivalent of
|
|
this switch (<tt/.AUTOIMPORT/, see control command section below) to enable
|
|
auto imported symbols for the runtime library. However, the compiler is
|
|
supposed to generate code that runs through the assembler without
|
|
problems, something which is not always true for assembler programmers.
|
|
|
|
|
|
<tag><tt>-V, --version</tt></tag>
|
|
|
|
Print the version number of the assembler. If you send any suggestions
|
|
or bugfixes, please include the version number.
|
|
|
|
|
|
<tag><tt>-Wn</tt></tag>
|
|
|
|
Set the warning level for the assembler. Using -W2 the assembler will
|
|
even warn about such things like unused imported symbols. The default
|
|
warning level is 1, and it would probably be silly to set it to
|
|
something lower.
|
|
|
|
</descrip>
|
|
|
|
|
|
|
|
<sect>Input format<p>
|
|
|
|
The assembler accepts the standard 6502/65816 assembler syntax. One line
|
|
may contain a label (which is identified by a colon), and, in addition to
|
|
the label, an assembler mnemonic, a macro, or a control command (see
|
|
section 6 for supported control commands). Alternatively, the line may
|
|
contain a symbol definition using the '=' token. Everything after a
|
|
semicolon is handled as a comment (that is, it is ignored).
|
|
|
|
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
|
|
</verb></tscreen>
|
|
|
|
The assembler accepts all valid 6502 mnemonics when in 6502 mode (the
|
|
default). The assembler accepts all valid 65SC02 mnemonics when in 65SC02
|
|
mode (after a <tt/.PC02/ command is found). The assembler accepts all valid
|
|
65816 mnemonics with a few exceptions after a .P816 command is found.
|
|
These exceptions are listed below.
|
|
|
|
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>
|
|
|
|
Evaluation of banked expressions in 65816 mode differs slightly from the
|
|
official syntax:
|
|
|
|
Instead of accepting a 24 bit address (something that is difficult for
|
|
the assembler to determine and would have required one more special
|
|
.import command), the bank and the absolute address in that bank are
|
|
separated by a dot:
|
|
|
|
<tscreen><verb>
|
|
jsl 3.$1234 ; Call subroutine at $1234 in bank 3
|
|
</verb></tscreen>
|
|
|
|
For literal values, the assembler accepts the widely used number formats:
|
|
A preceeding '$' denotes a hex value, a preceeding '%' denotes a
|
|
binary value, and a bare number is interpeted as a decimal. There are
|
|
currently no octal values and no floats.
|
|
|
|
|
|
|
|
<sect>Expressions
|
|
|
|
<p>
|
|
All expressions are evaluated with (at least) 32 bit precision. An
|
|
expression may contain constant values and any combination of internal and
|
|
external symbols. Expressions that cannot be evaluated at assembly time
|
|
are stored inside the object file for evaluation by the linker.
|
|
Expressions referencing imported symbols must always be evaluated by the
|
|
linker.
|
|
|
|
Sometimes, the assembler must know about the size of the value that is the
|
|
result of an expression. This is usually the case, if a decision has to be
|
|
made, to generate a zero page or an absolute memory references. In this
|
|
case, the assembler has to make some assumptions about the result of an
|
|
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 '>'/'<' 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,
|
|
it's 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
|
|
time, the linker will evaluate it and check for range errors as soon as
|
|
the result is known.
|
|
|
|
|
|
<bf>Boolean expressions:</bf>
|
|
|
|
In the context of a boolean expression, any non zero value is evaluated as
|
|
true, any other value to false. The result of a boolean expression is 1 if
|
|
it's true, and zero if it's false. There are boolean operators with extrem
|
|
low precedence with version 2.x (where x > 0). The <tt/.AND/ and <tt/.OR/
|
|
operators are shortcut operators. That is, if the result of the expression is
|
|
already known, after evaluating the left hand side, the right hand side is
|
|
not evaluated.
|
|
|
|
|
|
Available operators sorted by precedence:
|
|
|
|
<tscreen><verb>
|
|
Op Description Precedence
|
|
-------------------------------------------------------------------
|
|
.CONCAT Builtin function 0
|
|
.LEFT Builtin function 0
|
|
.MID Builtin function 0
|
|
.RIGHT Builtin function 0
|
|
.STRING Builtin function 0
|
|
|
|
* Builtin pseudo variable (r/o) 1
|
|
.BLANK Builtin function 1
|
|
.CONST Builtin function 1
|
|
.CPU Builtin pseudo variable (r/o) 1
|
|
.DEFINED Builtin function 1
|
|
.MATCH Builtin function 1
|
|
.TCOUNT Builtin function 1
|
|
.XMATCH Builtin function 1
|
|
.PARAMCOUNT Builtin pseudo variable (r/o) 1
|
|
.REFERENCED Builtin function 1
|
|
:: Global namespace override 1
|
|
+ Unary plus 1
|
|
- Unary minus 1
|
|
~ Unary bitwise not 1
|
|
.BITNOT Unary bitwise not 1
|
|
< Low byte operator 1
|
|
> High byte operator 1
|
|
|
|
* Multiplication 2
|
|
/ Division 2
|
|
.MOD Modulo operation 2
|
|
& Bitwise and 2
|
|
.BITAND Bitwise and 2
|
|
^ Bitwise xor 2
|
|
.BITXOR Bitwise xor 2
|
|
<< Shift left operator 2
|
|
.SHL Shift left operator 2
|
|
>> Shift right operator 2
|
|
.SHR Shift right operator 2
|
|
|
|
+ Binary plus 3
|
|
- Binary minus 3
|
|
| Binary or 3
|
|
.BITOR Binary or 3
|
|
|
|
= Compare operation (equal) 4
|
|
<> Compare operation (not equal) 4
|
|
< Compare operation (less) 4
|
|
> Compare operation (greater) 4
|
|
<= Compare operation (less or equal) 4
|
|
>= Compare operation (greater or equal) 4
|
|
|
|
&& Boolean and 5
|
|
.AND Boolean and 5
|
|
.XOR Boolean xor 5
|
|
|
|
|| Boolean or 6
|
|
.OR Boolean or 6
|
|
|
|
! Boolean not 7
|
|
.NOT Boolean not 7
|
|
</verb></tscreen>
|
|
|
|
|
|
To force a specific order of evaluation, braces may be used as usual.
|
|
|
|
Some of the pseudo variables mentioned above need some more explanation:
|
|
|
|
* This symbol is replaced by the value of the program
|
|
counter at start of the current instruction. Note, that
|
|
'*' yields a rvalue, that means, you cannot assign to it.
|
|
Use <tt/.ORG/ to set the program counter in sections with
|
|
absolute code.
|
|
|
|
|
|
|
|
<sect>Symbols and labels
|
|
|
|
<p>
|
|
The assembler allows you to use symbols instead of naked values to make
|
|
the source more readable. There are a lot of different ways to define and
|
|
use symbols and labels, giving a lot of flexibility.
|
|
|
|
<descrip>
|
|
|
|
|
|
<tag/Numeric constants/
|
|
|
|
Numeric constants are defined using the equal sign. After doing
|
|
|
|
<tscreen><verb>
|
|
two = 2
|
|
</verb></tscreen>
|
|
|
|
may use the symbol "two" in every place where a number is expected,
|
|
and it is evaluated to the value 2 in this context. An example would be
|
|
|
|
<tscreen><verb>
|
|
four = two * two
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag/Standard labels/
|
|
|
|
A label is defined by writing the name of the label at the start of
|
|
the line (before any instruction mnemonic, macro or pseudo
|
|
directive), followed by a colon. This will declare a symbol with the
|
|
given name and the value of the current program counter.
|
|
|
|
|
|
<tag/Local labels and symbols/
|
|
|
|
Using the <tt/.PROC/ directive, it is possible to create regions of code
|
|
where the names of labels and symbols are local to this region. They
|
|
are not know outside and cannot be accessed from there. Such regions
|
|
may be nested like PROCEDUREs in Pascal.
|
|
|
|
See the description of the <tt/.PROC/ directive for more information.
|
|
|
|
<tag/Cheap local labels/
|
|
|
|
Cheap local labels are defined like standard labels, but the name of
|
|
the label must begin with a special symbol (usually '@', but this can
|
|
be changed by the <tt/.LOCALCHAR/ directive).
|
|
|
|
Cheap local labels are visible only between two no cheap labels. As
|
|
soon as a standard symbol is encountered (this may also be a local
|
|
symbol if inside a region defined with the .PROC directive), the
|
|
cheap local symbol goes out of scope.
|
|
|
|
You may use cheap local labels as an easy way to reuse common label
|
|
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!
|
|
</verb></tscreen>
|
|
|
|
<tag/Unnamed labels/
|
|
|
|
If you really want to write messy code, there are also unnamed
|
|
labels. These labels do not have a name (you guessed that already,
|
|
didn't you?). A colon is used to mark the absence of the name.
|
|
|
|
Unnamed labels may be accessed by using the colon plus several minus
|
|
or plus characters as a label designator. Using the '-' characters
|
|
will create a back reference (use the n'th label backwards), using
|
|
'+' will create a forward reference (use the n'th label in forward
|
|
direction). An example will help to 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
|
|
</verb></tscreen>
|
|
|
|
As you can see from the example, unnamed labels will make even short
|
|
sections of code hard to understand, because you have to count labels
|
|
to find branch targets (this is the reason why I for my part do
|
|
prefer the "cheap" local labels). Nevertheless, unnamed labels are
|
|
convenient in some situations, so it's your decision.
|
|
|
|
<tag/Using macros to define labels and constants/
|
|
|
|
While there are drawbacks with this approach, it may be handy in some
|
|
situations. Using <tt/.DEFINE/, it is possible to define symbols or
|
|
constants that may be used elsewhere. Since the macro facility works
|
|
on a very low level, there is no scoping. On the other side, you may
|
|
also define string constants this way (this is not possible with the
|
|
other symbol types).
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.DEFINE two 2
|
|
.DEFINE version "SOS V2.3"
|
|
|
|
four = two * two ; Ok
|
|
.byte version ; Ok
|
|
|
|
.PROC ; Start local scope
|
|
two = 3 ; Will give "2 = 3" - invalid!
|
|
.ENDPROC
|
|
</verb></tscreen>
|
|
|
|
</descrip>
|
|
|
|
|
|
If <tt/.DEBUGINFO/ is enabled (or -g is given on the command line), global,
|
|
local and cheap local labels are written to the object file and will be
|
|
available in the symbol file via the linker. Unnamed labels are not
|
|
written to the object file, because they don't have a name which would
|
|
allow to access them.
|
|
|
|
|
|
|
|
<sect>Control commands
|
|
|
|
<p>
|
|
Here's a list of all control commands and a description, what they do:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt><idx>.A16</idx></tt></tag>
|
|
|
|
Valid only in 65816 mode. Switch the accumulator to 16 bit.
|
|
|
|
Note: This command will not emit any code, it will tell the assembler to
|
|
create 16 bit operands for immediate accumulator adressing mode.
|
|
|
|
See also: <tt/.SMART/
|
|
|
|
|
|
<tag><tt><idx>.A8</idx></tt></tag>
|
|
|
|
Valid only in 65816 mode. Switch the accumulator to 8 bit.
|
|
|
|
Note: This command will not emit any code, it will tell the assembler to
|
|
create 8 bit operands for immediate accu adressing mode.
|
|
|
|
See also: <tt/.SMART/
|
|
|
|
|
|
<tag><tt><idx>.ADDR</idx></tt></tag>
|
|
|
|
Define word sized data. In 6502 mode, this is an alias for <tt/.WORD/ and
|
|
may be used for better readability if the data words are address values.
|
|
In 65816 mode, the address is forced to be 16 bit wide to fit into the
|
|
current segment. See also <tt/.FARADDR/. The command must be followed by a
|
|
sequence of (not necessarily constant) expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.addr $0D00, $AF13, _Clear
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.ALIGN</idx></tt></tag>
|
|
|
|
Align data to a given boundary. The command expects a constant integer
|
|
argument that must be a power of two, plus an optional second argument
|
|
in byte range. If there is a second argument, it is used as fill value,
|
|
otherwise the value defined in the linker configuration file is used
|
|
(the default for this value is zero).
|
|
|
|
Since alignment depends on the base address of the module, you must
|
|
give the same (or a greater) alignment for the segment when linking.
|
|
The linker will give you a warning, if you don't do that.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.align 256
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.ASCIIZ</idx></tt></tag>
|
|
|
|
Define a string with a trailing zero.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
Msg: .asciiz "Hello world"
|
|
</verb></tscreen>
|
|
|
|
This will put the string "Hello world" followed by a binary zero into
|
|
the current segment. There may be more strings separated by commas, but
|
|
the binary zero is only appended once (after the last one).
|
|
|
|
|
|
<tag><tt><idx>.AUTOIMPORT</idx></tt></tag>
|
|
|
|
Is followd by a plus or a minus character. When switched on (using a
|
|
+), undefined symbols are automatically marked as import instead of
|
|
giving errors. When switched off (which is the default so this does not
|
|
make much sense), this does not happen and an error message is
|
|
displayed. The state of the autoimport flag is evaluated when the
|
|
complete source was translated, before outputing actual code, so it is
|
|
<em/not/ possible to switch this feature on or off for separate sections
|
|
of code. The last setting is used for all symbols.
|
|
|
|
You should probably not use this switch because it delays error
|
|
messages about undefined symbols until the link stage. The cc65
|
|
compiler (which is supposed to produce correct assembler code in all
|
|
circumstances, something which is not true for most assembler
|
|
programmers) will insert this command to avoid importing each and every
|
|
routine from the runtime library.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.autoimport + ; Switch on auto import
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.BLANK</idx></tt></tag>
|
|
|
|
Builtin function. The function evaluates its argument in braces and
|
|
yields "false" if the argument is non blank (there is an argument), and
|
|
"true" if there is no argument. As an example, the <tt/.IFBLANK/ statement
|
|
may be replaced by
|
|
|
|
<tscreen><verb>
|
|
.if .blank(arg)
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.BSS</idx></tt></tag>
|
|
|
|
Switch to the BSS segment. The name of the BSS segment is always "BSS",
|
|
so this is a shortcut for
|
|
|
|
<tscreen><verb>
|
|
.segment "BSS"
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.SEGMENT/ command.
|
|
|
|
|
|
<tag><tt><idx>.BYTE</idx></tt></tag>
|
|
|
|
Define byte sized data. Must be followed by a sequence of (byte ranged)
|
|
expressions or strings.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.byte "Hello world", $0D, $00
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.CASE</idx></tt></tag>
|
|
|
|
Switch on or off case sensitivity on identifiers. The default is off
|
|
(that is, identifiers are case sensitive), but may be changed by the
|
|
-i switch on the command line.
|
|
The command must be followed by a '+' or '-' character to switch the
|
|
option on or off respectively.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.case - ; Identifiers are not case sensitive
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.CODE</idx></tt></tag>
|
|
|
|
Switch to the CODE segment. The name of the CODE segment is always
|
|
"CODE", so this is a shortcut for
|
|
|
|
<tscreen><verb>
|
|
.segment "CODE"
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.SEGMENT/ command.
|
|
|
|
|
|
<tag><tt><idx>.CONCAT</idx></tt></tag>
|
|
|
|
Builtin function. The function allows to concatenate a list of string
|
|
constants separated by commas. The result is a string constant that
|
|
is the concatentation of all arguments. This function is most useful
|
|
in macros and when used together with the <tt/.STRING/ builtin function.
|
|
The function may be used in any case where a string constant is
|
|
expected.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.include .concat ("myheader", ".", "inc)
|
|
</verb></tscreen>
|
|
|
|
This is the same as the command
|
|
|
|
<tscreen><verb>
|
|
.include "myheader.inc"
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.CONST</idx></tt></tag>
|
|
|
|
Builtin function. The function evaluates its argument in braces and
|
|
yields "true" if the argument is a constant expression (that is, an
|
|
expression that yields a constant value at assembly time) and "false"
|
|
otherwise. As an example, the .IFCONST statement may be replaced by
|
|
|
|
<tscreen><verb>
|
|
.if .const(a + 3)
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.CPU</idx></tt></tag>
|
|
|
|
Reading this pseudo variable will give a constant integer value that
|
|
tells which instruction set is currently enabled. Possible values are:
|
|
|
|
<tscreen><verb>
|
|
0 --> 6502
|
|
1 --> 65SC02
|
|
2 --> 65SC816
|
|
3 --> SunPlus SPC
|
|
</verb></tscreen>
|
|
|
|
It may be used to replace the .IFPxx pseudo instructions or to construct
|
|
even more complex expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.if (.cpu = 0) .or (.cpu = 1)
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
.else
|
|
phx
|
|
phy
|
|
.endif
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.DATA</idx></tt></tag>
|
|
|
|
Switch to the DATA segment. The name of the DATA segment is always
|
|
"DATA", so this is a shortcut for
|
|
|
|
<tscreen><verb>
|
|
.segment "DATA"
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.SEGMENT/ command.
|
|
|
|
|
|
<tag><tt><idx>.DBYT</idx></tt></tag>
|
|
|
|
Define word sized data with the hi and lo bytes swapped (use <tt/.WORD/ to
|
|
create word sized data in native 65XX format). Must be followed by a
|
|
sequence of (word ranged) expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.dbyt $1234, $4512
|
|
</verb></tscreen>
|
|
|
|
This will emit the bytes
|
|
|
|
<tscreen><verb>
|
|
$12 $34 $45 $12
|
|
</verb></tscreen>
|
|
|
|
into the current segment in that order.
|
|
|
|
|
|
<tag><tt><idx>.DEBUGINFO</idx></tt></tag>
|
|
|
|
Switch on or off debug info generation. The default is off (that is,
|
|
the object file will not contain debug infos), but may be changed by the
|
|
-g switch on the command line.
|
|
The command must be followed by a '+' or '-' character to switch the
|
|
option on or off respectively.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.debuginfo + ; Generate debug info
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.DEFINE</idx></tt></tag>
|
|
|
|
Start a define style macro definition. The command is followed by an
|
|
identifier (the macro name) and optionally by a list of formal arguments
|
|
in braces.
|
|
See separate section about macros.
|
|
|
|
|
|
<tag><tt><idx>.DEF,</idx> <idx>.DEFINED</idx></tt></tag>
|
|
|
|
Builtin function. The function expects an identifier as argument in
|
|
braces. The argument is evaluated, and the function yields "true" if the
|
|
identifier is a symbol that is already defined somewhere in the source
|
|
file up to the current position. Otherwise the function yields false. As
|
|
an example, the <tt/.IFDEF/ statement may be replaced by
|
|
|
|
<tscreen><verb>
|
|
.if .defined(a)
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.DWORD</idx></tt></tag>
|
|
|
|
Define dword sized data (4 bytes) Must be followed by a sequence of
|
|
expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.dword $12344512, $12FA489
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.ELSE</idx></tt></tag>
|
|
|
|
Conditional assembly: Reverse the current condition.
|
|
|
|
|
|
<tag><tt><idx>.ELSEIF</idx></tt></tag>
|
|
|
|
Conditional assembly: Reverse current condition and test a new one.
|
|
|
|
|
|
<tag><tt><idx>.END</idx></tt></tag>
|
|
|
|
Forced end of assembly. Assembly stops at this point, even if the command
|
|
is read from an include file.
|
|
|
|
|
|
<tag><tt><idx>.ENDIF</idx></tt></tag>
|
|
|
|
Conditional assembly: Close a <tt/.IF.../ or <tt/.ELSE/ branch.
|
|
|
|
|
|
<tag><tt><idx>.ENDMAC,</idx> <idx>.ENDMACRO</idx></tt></tag>
|
|
|
|
End of macro definition (see separate section).
|
|
|
|
|
|
<tag><tt><idx>.ENDPROC</idx></tt></tag>
|
|
|
|
End of local lexical level (see <tt/.PROC/).
|
|
|
|
|
|
<tag><tt><idx>.ENDREP,</idx> <idx>.ENDREPEAT</idx></tt></tag>
|
|
|
|
End a <tt/.REPEAT/ block. See the <tt/.REPEAT/ command.
|
|
|
|
|
|
<tag><tt><idx>.ERROR</idx></tt></tag>
|
|
|
|
Force an assembly error. The assembler will output an error message
|
|
preceeded by "User error" and will <em/not/ produce an object file.
|
|
|
|
This command may be used to check for initial conditions that must be
|
|
set before assembling a source file.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.if foo = 1
|
|
...
|
|
.elseif bar = 1
|
|
...
|
|
.else
|
|
.error "Must define foo or bar!"
|
|
.endif
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.WARNING/ and <tt/.OUT/ directives.
|
|
|
|
|
|
<tag><tt><idx>.EXITMAC,</idx> <idx>.EXITMACRO</idx></tt></tag>
|
|
|
|
Abort a macro expansion immidiately. This command is often useful in
|
|
recursive macros. See separate chapter about macros.
|
|
|
|
|
|
<tag><tt><idx>.EXPORT</idx></tt></tag>
|
|
|
|
Make symbols accessible from other modules. Must be followed by a comma
|
|
separated list of symbols to export.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.export foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.EXPORTZP</idx></tt></tag>
|
|
|
|
Make symbols accessible from other modules. Must be followed by a comma
|
|
separated list of symbols to export. The exported symbols are explicitly
|
|
marked as zero page symols.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.exportzp foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.FARADDR</idx></tt></tag>
|
|
|
|
Define far (24 bit) address data. The command must be followed by a
|
|
sequence of (not necessarily constant) expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.faraddr DrawCircle, DrawRectangle, DrawHexagon
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.FEATURE</idx></tt></tag>
|
|
|
|
This directive may be used to enable one or more compatibility features
|
|
of the assembler. While the use of <tt/.FEATURE/ should be avoided when
|
|
possible, it may be useful when porting sources written for other
|
|
assemblers. There is no way to switch a feature off, once you have
|
|
enabled it, so using
|
|
|
|
<tscreen><verb>
|
|
.FEATURE xxx
|
|
</verb></tscreen>
|
|
|
|
will enable the feature until end of assembly is reached.
|
|
|
|
The following features are available:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt<idx>>dollar_is_pc</idx></tt></tag>
|
|
|
|
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<idx>>labels_without_colons</idx></tt></tag>
|
|
|
|
Allow labels without a trailing colon. These labels are only accepted,
|
|
if they start at the beginning of a line (no leading white space).
|
|
|
|
<tag><tt<idx>>loose_string_term</idx></tt></tag>
|
|
|
|
Accept single quotes as well as double quotes as terminators for string
|
|
constants.
|
|
|
|
<tag><tt<idx>>at_in_identifiers</idx></tt></tag>
|
|
|
|
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<idx>>dollar_in_identifiers</idx></tt></tag>
|
|
|
|
Accept the dollar sign (`$') as a valid character in identifiers. The
|
|
at character is not allowed to start an identifier, even with this
|
|
feature enabled.
|
|
|
|
</descrip>
|
|
|
|
|
|
<tag><tt><idx>.FILEOPT,</idx> <idx>.FOPT</idx></tt></tag>
|
|
|
|
Insert an option string into the object file. There are two forms of
|
|
this command, one specifies the option by a keyword, the second
|
|
specifies it as a number. Since usage of the second one needs knowledge
|
|
of the internal encoding, its use is not recommended and I will only
|
|
describe the first form here.
|
|
|
|
The command is followed by one of the keywords
|
|
|
|
<tscreen><verb>
|
|
author
|
|
comment
|
|
compiler
|
|
</verb></tscreen>
|
|
|
|
a comma and a string. The option is written into the object file
|
|
together with the string value. This is currently unidirectional and
|
|
there is no way to actually use these options once they are in the
|
|
object file.
|
|
|
|
Examples:
|
|
|
|
<tscreen><verb>
|
|
.fileopt comment, "Code stolen from my brother"
|
|
.fileopt compiler, "BASIC 2.0"
|
|
.fopt author, "J. R. User"
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.GLOBAL</idx></tt></tag>
|
|
|
|
Declare symbols as global. Must be followed by a comma separated list
|
|
of symbols to declare. Symbols from the list, that are defined somewhere
|
|
in the source, are exported, all others are imported. An additional
|
|
explicit <tt/.IMPORT/ or <tt/.EXPORT/ command for the same symbol is
|
|
allowed.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.global foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.GLOBALZP</idx></tt></tag>
|
|
|
|
Declare symbols as global. Must be followed by a comma separated list
|
|
of symbols to declare. Symbols from the list, that are defined
|
|
somewhere in the source, are exported, all others are imported. An
|
|
additional explicit <tt/.IMPORT/ or <tt/.EXPORT/ command for the same
|
|
symbol is explicitly allowed. The symbols in the list are explicitly
|
|
marked as zero page symols.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.globalzp foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.I16</idx></tt></tag>
|
|
|
|
Valid only in 65816 mode. Switch the index registers to 16 bit.
|
|
|
|
Note: This command will not emit any code, it will tell the assembler to
|
|
create 16 bit operands for immediate operands.
|
|
|
|
See also the <tt/.SMART/ command.
|
|
|
|
|
|
<tag><tt><idx>.I8</idx></tt></tag>
|
|
|
|
Valid only in 65816 mode. Switch the index registers to 8 bit.
|
|
|
|
Note: This command will not emit any code, it will tell the assembler to
|
|
create 8 bit operands for immediate operands.
|
|
|
|
See also the <tt/.SMART/ command.
|
|
|
|
|
|
<tag><tt><idx>.IF</idx></tt></tag>
|
|
|
|
Conditional assembly: Evalute an expression and switch assembler output
|
|
on or off depending on the expression. The expression must be a constant
|
|
expression, that is, all operands must be defined.
|
|
|
|
A expression value of zero evaluates to FALSE, any other value evaluates
|
|
to TRUE.
|
|
|
|
|
|
<tag><tt><idx>.IFBLANK</idx></tt></tag>
|
|
|
|
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/.ELSE/, <tt/.ELSEIF/ or <tt/.ENDIF/ directive.
|
|
|
|
This command is often used to check if a macro parameter was given.
|
|
Since an empty macro parameter will evaluate to nothing, the condition
|
|
will evaluate to FALSE if an empty parameter was given.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.macro arg1, arg2
|
|
.ifblank arg2
|
|
lda #arg1
|
|
.else
|
|
lda #arg2
|
|
.endif
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
See also: <tt/.BLANK/
|
|
|
|
|
|
<tag><tt><idx>.IFCONST</idx></tt></tag>
|
|
|
|
Conditional assembly: Evaluate an expression and switch assembler output
|
|
on or off depending on the constness of the expression.
|
|
|
|
A const expression evaluates to to TRUE, a non const expression (one
|
|
containing an imported or currently undefined symbol) evaluates to
|
|
FALSE.
|
|
|
|
See also: <tt/.CONST/
|
|
|
|
|
|
<tag><tt><idx>.IFDEF</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if a symbol is defined. Must be followed by
|
|
a symbol name. The condition is true if the the given symbol is already
|
|
defined, and false otherwise.
|
|
|
|
See also: <tt/.DEFINED/
|
|
|
|
|
|
<tag><tt><idx>.IFNBLANK</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if there are any remaining tokens in this
|
|
line, and evaluate to TRUE if this is the case, and to FALSE otherwise.
|
|
If the condition is not true, further lines are not assembled until
|
|
an <tt/.ELSE/, <tt/.ELSEIF/ or <tt/.ENDIF/ directive.
|
|
|
|
This command is often used to check if a macro parameter was given.
|
|
Since an empty macro parameter will evaluate to nothing, the condition
|
|
will evaluate to FALSE if an empty parameter was given.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.macro arg1, arg2
|
|
lda #arg1
|
|
.ifnblank arg2
|
|
lda #arg2
|
|
.endif
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
See also: <tt/.BLANK/
|
|
|
|
|
|
<tag><tt><idx>.IFNDEF</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if a symbol is defined. Must be followed by
|
|
a symbol name. The condition is true if the the given symbol is not
|
|
defined, and false otherwise.
|
|
|
|
See also: <tt/.DEFINED/
|
|
|
|
|
|
<tag><tt><idx>.IFNREF</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if a symbol is referenced. Must be followed
|
|
by a symbol name. The condition is true if if the the given symbol was
|
|
not referenced before, and false otherwise.
|
|
|
|
See also: <tt/.REFERENCED/
|
|
|
|
|
|
<tag><tt><idx>.IFP02</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if the assembler is currently in 6502 mode
|
|
(see <tt/.P02/ command).
|
|
|
|
|
|
<tag><tt><idx>.IFP816</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if the assembler is currently in 65816 mode
|
|
(see <tt/.P816/ command).
|
|
|
|
|
|
<tag><tt><idx>.IFPC02</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if the assembler is currently in 65C02 mode
|
|
(see <tt/.PC02/ command).
|
|
|
|
|
|
<tag><tt><idx>.IFREF</idx></tt></tag>
|
|
|
|
Conditional assembly: Check if a symbol is referenced. Must be followed
|
|
by a symbol name. The condition is true if if the the given symbol was
|
|
referenced before, and false otherwise.
|
|
|
|
This command may be used to build subroutine libraries in include files
|
|
(you may use separate object modules for this purpose too).
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.ifref ToHex ; If someone used this subroutine
|
|
ToHex: tay ; Define subroutine
|
|
lda HexTab,y
|
|
rts
|
|
.endif
|
|
</verb></tscreen>
|
|
|
|
See also: <tt/.REFERENCED/
|
|
|
|
|
|
<tag><tt><idx>.IMPORT</idx></tt></tag>
|
|
|
|
Import a symbol from another module. The command is followed by a comma
|
|
separated list of symbols to import.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.import foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.IMPORTZP</idx></tt></tag>
|
|
|
|
Import a symbol from another module. The command is followed by a comma
|
|
separated list of symbols to import. The symbols are explicitly imported
|
|
as zero page symbols (that is, symbols with values in byte range).
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.includezp foo, bar
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.INCBIN</idx></tt></tag>
|
|
|
|
Include a file as binary data. The command expects a string argument
|
|
that is the name of a file to include literally in the current segment.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.incbin "sprites.dat"
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.INCLUDE</idx></tt></tag>
|
|
|
|
Include another file. Include files may be nested up to a depth of 16.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.include "subs.inc"
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.LEFT</idx></tt></tag>
|
|
|
|
Builtin function. Extracts the left part of a given token list.
|
|
|
|
Syntax:
|
|
|
|
<tscreen><verb>
|
|
.LEFT (<int expr>, <token list>)
|
|
</verb></tscreen>
|
|
|
|
The first integer expression gives the number of tokens to extract from
|
|
the token list. The second argument is the token list itself.
|
|
|
|
Example:
|
|
|
|
To check in a macro if the given argument has a '#' as first token
|
|
(immidiate addressing mode), use something like this:
|
|
|
|
<tscreen><verb>
|
|
.macro ldax arg
|
|
...
|
|
.if (.match (.left (1, arg), #))
|
|
|
|
; ldax called with immidiate operand
|
|
...
|
|
|
|
.endif
|
|
...
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.MID/ and <tt/.RIGHT/ builtin functions.
|
|
|
|
|
|
<tag><tt><idx>.LINECONT</idx></tt></tag>
|
|
|
|
Switch on or off line continuations using the backslash character
|
|
before a newline. The option is off by default.
|
|
Note: Line continuations do not work in a comment. A backslash at the
|
|
end of a comment is treated as part of the comment and does not trigger
|
|
line continuation.
|
|
The command must be followed by a '+' or '-' character to switch the
|
|
option on or off respectively.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.linecont + ; Allow line continuations
|
|
|
|
lda \
|
|
#$20 ; This is legal now
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.LIST</idx></tt></tag>
|
|
|
|
Enable output to the listing. The command must be followed by a boolean
|
|
switch ("on", "off", "+" or "-") and will enable or disable listing
|
|
output.
|
|
The option has no effect if the listing is not enabled by the command line
|
|
switch -l. If -l is used, an internal counter is set to 1. Lines are output
|
|
to the listing file, if the counter is greater than zero, and suppressed if
|
|
the counter is zero. Each use of <tt/.LIST/ will increment or decrement the
|
|
counter.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.list on ; Enable listing output
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.LISTBYTES</idx></tt></tag>
|
|
|
|
Set, how many bytes are shown in the listing for one source line. The
|
|
default is 12, so the listing will show only the first 12 bytes for any
|
|
source line that generates more than 12 bytes of code or data.
|
|
The directive needs an argument, which is either "unlimited", or an
|
|
integer constant in the range 4..255.
|
|
|
|
Examples:
|
|
|
|
<tscreen><verb>
|
|
.listbytes unlimited ; List all bytes
|
|
.listbytes 12 ; List the first 12 bytes
|
|
.incbin "data.bin" ; Include large binary file
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.LOCAL</idx></tt></tag>
|
|
|
|
This command may only be used inside a macro definition. It declares a
|
|
list of identifiers as local to the macro expansion.
|
|
|
|
A problem when using macros are labels: Since they don't change their
|
|
name, you get a "duplicate symbol" error if the macro is expanded the
|
|
second time. Labels declared with <tt/.LOCAL/ have their name mapped to
|
|
an internal unique name (<tt/___ABCD__/) with each macro invocation.
|
|
|
|
Some other assemblers start a new lexical block inside a macro
|
|
expansion. This has some drawbacks however, since that will not allow
|
|
<em/any/ symbol to be visible outside a macro, a feature that is sometimes
|
|
useful. The <tt/.LOCAL/ command is in my eyes a better way to address
|
|
the problem.
|
|
|
|
You get an error when using <tt/.LOCAL/ outside a macro.
|
|
|
|
|
|
<tag><tt><idx>.LOCALCHAR</idx></tt></tag>
|
|
|
|
Defines the character that start "cheap" local labels. You may use one
|
|
of '@' and '?' as start character. The default is '@'.
|
|
|
|
Cheap local labels are labels that are visible only between two non
|
|
cheap labels. This way you can reuse identifiers like "<tt/loop/" without
|
|
using explicit lexical nesting.
|
|
|
|
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!
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.MACPACK</idx></tt></tag>
|
|
|
|
Insert a predefined macro package. The command is followed by an
|
|
identifier specifying the macro package to insert. Available macro
|
|
packages are:
|
|
|
|
generic Defines generic macros like add and sub.
|
|
longbranch Defines conditional long jump macros.
|
|
|
|
Including a macro package twice, or including a macro package that
|
|
redefines already existing macros will lead to an error.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.macpack longbranch ; Include macro package
|
|
|
|
cmp #$20 ; Set condition codes
|
|
jne Label ; Jump long on condition
|
|
</verb></tscreen>
|
|
|
|
See separate section about macros packages.
|
|
|
|
|
|
<tag><tt><idx>.MAC,</idx> <idx>.MACRO</idx></tt></tag>
|
|
|
|
Start a classic macro definition. The command is followed by an identifier
|
|
(the macro name) and optionally by a comma separated list of identifiers
|
|
that are macro parameters.
|
|
See separate section about macros.
|
|
|
|
|
|
<tag><tt><idx>.MATCH</idx></tt></tag>
|
|
|
|
Builtin function. Matches two token lists against each other. This is
|
|
most useful within macros, since macros are not stored as strings, but
|
|
as lists of tokens.
|
|
|
|
The syntax is
|
|
|
|
<tscreen><verb>
|
|
.MATCH(<token list #1>, <token list #2>)
|
|
</verb></tscreen>
|
|
|
|
Both token list may contain arbitrary tokens with the exception of the
|
|
terminator token (comma resp. right parenthesis) and
|
|
|
|
<itemize>
|
|
<item>end-of-line
|
|
<item>end-of-file
|
|
</itemize>
|
|
|
|
Often a macro parameter is used for any of the token lists.
|
|
|
|
Please note that the function does only compare tokens, not token
|
|
attributes. So any number is equal to any other number, regardless of
|
|
the actual value. The same is true for strings. If you need to compare
|
|
tokens <em/and/ token attributes, use the <tt/.XMATCH/ function.
|
|
|
|
Example:
|
|
|
|
Assume the macro <tt/ASR/, that will shift right the accumulator by one, while
|
|
honoring the sign bit. The builtin processor instructions will allow an
|
|
optional "A" for accu addressing for instructions like <tt/ROL/ and <tt/ROR/.
|
|
We will use the <tt/.MATCH/ function to check for this and print and error
|
|
for invalid calls.
|
|
|
|
<tscreen><verb>
|
|
.macro asr arg
|
|
|
|
.if (.not .blank(arg)) .and (.not .match (arg, a))
|
|
.error "Syntax error"
|
|
.endif
|
|
|
|
cmp #$80 ; Bit 7 into carry
|
|
lsr a ; Shit carry into bit 7
|
|
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
The macro will only accept no arguments, or one argument that must be the
|
|
reserved keyword "A".
|
|
|
|
|
|
<tag><tt><idx>.MID</idx></tt></tag>
|
|
|
|
Builtin function. Takes a starting index, a count and a token list as
|
|
arguments. Will return part of the token list.
|
|
|
|
Syntax:
|
|
|
|
<tscreen><verb>
|
|
.MID (<int expr>, <int expr>, <token list>)
|
|
</verb></tscreen>
|
|
|
|
The first integer expression gives the starting token in the list (the
|
|
first token has index 0). The second integer expression gives the number
|
|
of tokens to extract from the token list. The third argument is the
|
|
token list itself.
|
|
|
|
Example:
|
|
|
|
To check in a macro if the given argument has a '<tt/#/' as first token
|
|
(immidiate addressing mode), use something like this:
|
|
|
|
<tscreen><verb>
|
|
.macro ldax arg
|
|
...
|
|
.if (.match (.mid (0, 1, arg), #))
|
|
|
|
; ldax called with immidiate operand
|
|
...
|
|
|
|
.endif
|
|
...
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.LEFT/ and <tt/.RIGHT/ builtin functions.
|
|
|
|
|
|
<tag><tt><idx>.ORG</idx></tt></tag>
|
|
|
|
Start a section of absolute code. The command is followed by a constant
|
|
expression that gives the new PC counter location for which the code is
|
|
assembled. Use <tt/.RELOC/ to switch back to relocatable code.
|
|
|
|
You may not switch segments while inside a section of absolute code.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.org $7FF ; Emit code starting at $7FF
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.OUT</idx></tt></tag>
|
|
|
|
Output a string to the console without producing an error. This command
|
|
is similiar to <tt/.ERROR/, however, it does not force an assembler error
|
|
that prevents the creation of an object file.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.out "This code was written by the codebuster(tm)"
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.WARNING/ and <tt/.ERROR/ directives.
|
|
|
|
|
|
<tag><tt><idx>.P02</idx></tt></tag>
|
|
|
|
Enable the 6502 instruction set, disable 65C02 and 65816 instructions.
|
|
This is the default if not overridden by the <tt/--cpu/ command line
|
|
option.
|
|
|
|
|
|
<tag><tt><idx>.P816</idx></tt></tag>
|
|
|
|
Enable the 65816 instruction set. This is a superset of the 65C02 and
|
|
6502 instruction sets.
|
|
|
|
|
|
<tag><tt><idx>.PAGELEN,</idx> <idx>.PAGELENGTH</idx></tt></tag>
|
|
|
|
Set the page length for the listing. Must be followed by an integer
|
|
constant. The value may be "unlimited", or in the range 32 to 127. The
|
|
statement has no effect if no listing is generated. The default value
|
|
is -1 but may be overridden by the <tt/--pagelength/ command line option.
|
|
Beware: Since the listing is generated after assembly is complete, you
|
|
cannot use multiple line lengths with one source. Instead, the value
|
|
set with the last <tt/.PAGELENGTH/ is used.
|
|
|
|
Examples:
|
|
|
|
<tscreen><verb>
|
|
.pagelength 66 ; Use 66 lines per listing page
|
|
|
|
.pagelength unlimited ; Unlimited page length
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.PARAMCOUNT</idx></tt></tag>
|
|
|
|
This builtin pseudo variable is only available in macros. It is replaced
|
|
by the actual number of parameters that were given in the macro
|
|
invocation.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.macro foo arg1, arg2, arg3
|
|
.if .paramcount <> 3
|
|
.error "Too few parameters for macro foo"
|
|
.endif
|
|
...
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.PC02</idx></tt></tag>
|
|
|
|
Enable the 65C02 instructions set. This instruction set includes all
|
|
6502 instructions.
|
|
|
|
|
|
<tag><tt><idx>.PROC</idx></tt></tag>
|
|
|
|
Start a nested lexical level. All new symbols from now on are in the
|
|
local lexical level and are not accessible from outside. Symbols defined
|
|
outside this local level may be accessed as long as their names are not
|
|
used for new symbols inside the level. Symbols names in other lexical
|
|
levels do not clash, so you may use the same names for identifiers. The
|
|
lexical level ends when the <tt/.ENDPROC/ command is read. Lexical levels
|
|
may be nested up to a depth of 16.
|
|
|
|
The command may be followed by an identifier, in this case the
|
|
identifier is declared in the outer level as a label having the value of
|
|
the program counter at the start of the lexical level.
|
|
|
|
Note: Macro names are always in the global level and in a separate name
|
|
space. There is no special reason for this, it's just that I've never
|
|
had any need for local macro definitions.
|
|
|
|
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
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.REF,</idx> <idx>.REFERENCED</idx></tt></tag>
|
|
|
|
Builtin function. The function expects an identifier as argument in
|
|
braces. The argument is evaluated, and the function yields "true" if the
|
|
identifier is a symbol that has already been referenced somewhere in the
|
|
source file up to the current position. Otherwise the function yields
|
|
false. As an example, the <tt/.IFREF/ statement may be replaced by
|
|
|
|
<tscreen><verb>
|
|
.if .referenced(a)
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.REPEAT</idx></tt></tag>
|
|
|
|
Repeat all commands between <tt/.REPEAT/ and <tt/.ENDREPEAT/ a constant
|
|
number of times. The command is followed by a constant expression that tells
|
|
how many times the commands in the body should get repeated. Optionally, a
|
|
comma and an identifier may be specified. If this identifier is found in
|
|
the body of the repeat statement, it is replaced by the current repeat
|
|
count (starting with zero for the first time the body is repeated).
|
|
|
|
<tt/.REPEAT/ statements may be nested. If you use the same repeat count
|
|
identifier for a nested <tt/.REPEAT/ statement, the one from the inner
|
|
level will be used, not the one from the outer level.
|
|
|
|
Example:
|
|
|
|
The following macro will emit a string that is "encrypted" in that all
|
|
characters of the string are XORed by the value $55.
|
|
|
|
<tscreen><verb>
|
|
.macro Crypt Arg
|
|
.repeat strlen(Arg), I
|
|
.byte strat(Arg, I) .xor $55
|
|
.endrep
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.RELOC</idx></tt></tag>
|
|
|
|
Switch back to relocatable mode. See the <tt/.ORG/ command.
|
|
|
|
|
|
<tag><tt><idx>.RES</idx></tt></tag>
|
|
|
|
Reserve storage. The command is followed by one or two constant
|
|
expressions. The first one is mandatory and defines, how many bytes of
|
|
storage should be defined. The second, optional expression must by a
|
|
constant byte value that will be used as value of the data. If there
|
|
is no fill value given, the linker will use the value defined in the
|
|
linker configuration file (default: zero).
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
; Reserve 12 bytes of memory with value $AA
|
|
.res 12, $AA
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.RIGHT</idx></tt></tag>
|
|
|
|
Builtin function. Extracts the right part of a given token list.
|
|
|
|
Syntax:
|
|
|
|
<tscreen><verb>
|
|
.RIGHT (<int expr>, <token list>)
|
|
</verb></tscreen>
|
|
|
|
The first integer expression gives the number of tokens to extract from
|
|
the token list. The second argument is the token list itself.
|
|
|
|
See also the <tt/.LEFT/ and <tt/.MID/ builtin functions.
|
|
|
|
|
|
<tag><tt><idx>.RODATA</idx></tt></tag>
|
|
|
|
Switch to the RODATA segment. The name of the RODATA segment is always
|
|
"RODATA", so this is a shortcut for
|
|
|
|
<tscreen><verb>
|
|
.segment "RODATA"
|
|
</verb></tscreen>
|
|
|
|
The RODATA segment is a segment that is used by the compiler for
|
|
readonly data like string constants. See also the <tt/.SEGMENT/ command.
|
|
|
|
|
|
<tag><tt><idx>.SEGMENT</idx></tt></tag>
|
|
|
|
Switch to another segment. Code and data is always emitted into a
|
|
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 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 names that would also be valid identifiers). There may also be
|
|
an optional attribute separated by a comma. Valid attributes are
|
|
"<tt/zeropage/" and "<tt/absolute/".
|
|
|
|
When specifying a segment for the first time, "absolute" is the
|
|
default. For all other uses, the attribute specified the first time
|
|
is the default.
|
|
|
|
"absolute" means that this is a segment with absolute addressing. That
|
|
is, the segment will reside somewhere in core memory outside the zero
|
|
page. "zeropage" means the opposite: The segment will be placed in the
|
|
zero 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
|
|
work as in other segments and will create absolute variable values.
|
|
|
|
Example:
|
|
|
|
<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
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.SMART</idx></tt></tag>
|
|
|
|
Switch on or off smart mode. The command must be followed by a '+' or
|
|
'-' character to switch the option on or off respectively. The default
|
|
is off (that is, the assembler doesn't try to be smart), but this
|
|
default may be changed by the -s switch on the command line.
|
|
|
|
In smart mode the assembler will track usage of the <tt/REP/ and <tt/SEP/
|
|
instructions in 65816 mode and update the operand sizes accordingly. If
|
|
the operand of such an instruction cannot be evaluated by the assembler
|
|
(for example, because the operand is an imported symbol), a warning is
|
|
issued. Beware: Since the assembler cannot trace the execution flow this
|
|
may lead to false results in some cases. If in doubt, use the <tt/.Inn/ and
|
|
<tt/.Ann/ instructions to tell the assembler about the current settings.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.smart ; Be smart
|
|
.smart - ; Stop being smart
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.STRAT</idx></tt></tag>
|
|
|
|
Builtin function. The function accepts a string and an index as
|
|
arguments and returns the value of the character at the given position
|
|
as an integer value. The index is zero based.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.macro M Arg
|
|
; Check if the argument string starts with '#'
|
|
.if (.strat (Arg, 0) = '#')
|
|
...
|
|
.endif
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.STRING</idx></tt></tag>
|
|
|
|
Builtin function. The function accepts an argument in braces and
|
|
converts this argument into a string constant. The argument may be an
|
|
identifier, or a constant numeric value.
|
|
Since you can use a string in the first place, the use of the function
|
|
may not be obvious. However, it is useful in macros, or more complex
|
|
setups.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
; Emulate other assemblers:
|
|
.macro section name
|
|
.segment .string(name)
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.STRLEN</idx></tt></tag>
|
|
|
|
Builtin function. The function accepts a string argument in braces and
|
|
eveluates to the length of the string.
|
|
|
|
Example:
|
|
|
|
The following macro encodes a string as a pascal style string with
|
|
a leading length byte.
|
|
|
|
<tscreen><verb>
|
|
.macro PString Arg
|
|
.byte .strlen(Arg), Arg
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.TCOUNT</idx></tt></tag>
|
|
|
|
Builtin function. The function accepts a token list in braces. The
|
|
function result is the number of tokens given as argument.
|
|
|
|
Example:
|
|
|
|
The <tt/ldax/ macro accepts the '#' token to denote immidiate addressing (as
|
|
with the normal 6502 instructions). To translate it into two separate 8 bit
|
|
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 immidiate operand
|
|
lda #<(.right (.tcount (arg)-1, arg))
|
|
ldx #>(.right (.tcount (arg)-1, arg))
|
|
.else
|
|
...
|
|
.endif
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.WARNING</idx></tt></tag>
|
|
|
|
Force an assembly warning. The assembler will output a warning message
|
|
preceeded by "User warning". This warning will always be output, even
|
|
if other warnings are disabled with the <tt/-W0/ command line option.
|
|
|
|
This command may be used to output possible problems when assembling
|
|
the source file.
|
|
|
|
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
|
|
</verb></tscreen>
|
|
|
|
See also the <tt/.ERROR/ and <tt/.OUT/ directives.
|
|
|
|
|
|
<tag><tt><idx>.WORD</idx></tt></tag>
|
|
|
|
Define word sized data. Must be followed by a sequence of (word ranged,
|
|
but not necessarily constant) expressions.
|
|
|
|
Example:
|
|
|
|
<tscreen><verb>
|
|
.word $0D00, $AF13, _Clear
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>.ZEROPAGE</idx></tt></tag>
|
|
|
|
Switch to the ZEROPAGE segment and mark it as direct (zeropage) segment.
|
|
The name of the ZEROPAGE segment is always "ZEROPAGE", so this is a
|
|
shortcut for
|
|
|
|
<tscreen><verb>
|
|
.segment "ZEROPAGE", zeropage
|
|
</verb></tscreen>
|
|
|
|
Because of the "zeropage" attribute, labels declared in this segment are
|
|
addressed using direct addressing mode if possible. You <em/must/ instruct
|
|
the linker to place this segment somewhere in the address range 0..$FF
|
|
otherwise you will get errors.
|
|
|
|
</descrip>
|
|
|
|
|
|
|
|
<sect>Macros
|
|
|
|
<p>
|
|
Macros may be thought of as "parametrized super instructions". Macros are
|
|
sequences of tokens that have a name. If that name is used in the source
|
|
file, the macro is "expanded", that is, it is replaced by the tokens that
|
|
were specified when the macro was defined.
|
|
|
|
In it's simplest form, a macro does not have parameters. Here's an
|
|
example:
|
|
|
|
<tscreen><verb>
|
|
.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
|
|
the code, whenever the macro is expanded. Macro expansion is simply done
|
|
by using the name, like this:
|
|
|
|
<tscreen><verb>
|
|
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
|
|
</verb></tscreen>
|
|
|
|
When calling the macro, you may give a parameter, and each occurence of
|
|
the name "addr" in the macro definition will be replaced by the given
|
|
parameter. So
|
|
|
|
<tscreen><verb>
|
|
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
|
|
</verb></tscreen>
|
|
|
|
A macro may have more than one parameter, in this case, the parameters
|
|
are separated by commas. You are free to give less parameters than the
|
|
macro actually takes in the definition. You may also leave intermediate
|
|
parameters empty. Empty parameters are replaced by empty space (that is,
|
|
they are removed when the macro is exanded). If you have a look at our
|
|
macro definition above, you will see, that replacing the "addr" parameter
|
|
by nothing will lead to wrong code in most lines. To help you, writing
|
|
macros with a variable parameter list, there are some control commands:
|
|
|
|
<tt/.IFBLANK/ tests the rest of the line and returns true, if there are any
|
|
tokens on the remainder of the line. Since empty parameters are replaced by
|
|
nothing, this may be used to test if a given parameter is empty.
|
|
<tt/.IFNBLANK/ tests the opposite.
|
|
|
|
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
|
|
</verb></tscreen>
|
|
|
|
This macro may be called as follows:
|
|
|
|
<tscreen><verb>
|
|
ldaxy 1, 2, 3 ; Load all three registers
|
|
|
|
ldaxy 1, , 3 ; Load only a and y
|
|
|
|
ldaxy , , 3 ; Load y only
|
|
</verb></tscreen>
|
|
|
|
There's another helper command for determining, which macro parameters are
|
|
valid: <tt/.PARAMCOUNT/. This command is replaced by the parameter count
|
|
given, <em/including/ intermediate empty macro 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
|
|
</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
|
|
</verb></tscreen>
|
|
|
|
There's also a special macro to help writing recursive macros:
|
|
<tt/.EXITMACRO/. This command will stop macro expansion immidiately:
|
|
|
|
<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
|
|
</verb></tscreen>
|
|
|
|
When expanding this 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
|
|
</verb></tscreen>
|
|
|
|
Now, with recursive macros, <tt/.IFBLANK/ and <tt/.PARAMCOUNT/, what else do
|
|
you need? 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
|
|
</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
|
|
clc
|
|
lda addr
|
|
adc #$01
|
|
sta addr
|
|
bcc Skip
|
|
inc addr+1
|
|
Skip:
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
But imagine what happens, if you use this macro twice? Since the label
|
|
"Skip" has the same name both times, you get a "duplicate symbol" error.
|
|
Without a way to circumvent this problem, macros are not as useful, as
|
|
they could be. One solution is, to start a new lexical block inside the
|
|
macro:
|
|
|
|
<tscreen><verb>
|
|
.macro inc16 addr
|
|
.proc
|
|
clc
|
|
lda addr
|
|
adc #$01
|
|
sta addr
|
|
bcc Skip
|
|
inc addr+1
|
|
Skip:
|
|
.endproc
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
Now the label is local to the block and not visible outside. However,
|
|
sometimes you want a label inside the macro to be visible outside. To make
|
|
that possible, there's a new command that's only usable inside a macro
|
|
definition: <tt/.LOCAL/. <tt/.LOCAL/ declares one or more symbols as local to
|
|
the macro expansion. The names of local variables are replaced by a unique
|
|
name in each separate macro expansion. So we could also solve the problem
|
|
above by using <tt/.LOCAL/:
|
|
|
|
<tscreen><verb>
|
|
.macro inc16 addr
|
|
.local Skip ; Make Skip a local symbol
|
|
clc
|
|
lda addr
|
|
adc #$01
|
|
sta addr
|
|
bcc Skip
|
|
inc addr+1
|
|
Skip: ; Not visible outside
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
Starting with version 2.5 of the assembler, there is a second macro type
|
|
available: C style macros using the <tt/.DEFINE/ directive. These macros are
|
|
similar to the classic macro type speified above, but behaviour is sometimes
|
|
different:
|
|
|
|
<itemize>
|
|
|
|
<item> Macros defined with <tt/.DEFINE/ may not span more than a line. You
|
|
may use line continuation (see <tt/.LINECONT/) to spread the
|
|
definition over more than one line for increased readability, but the
|
|
macro itself does not contain an end-of-line token.
|
|
|
|
<item> Macros defined with <tt/.DEFINE/ 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/.DEFINE/ style macros are allowed anywhere
|
|
in a line. So they are more versatile in some situations.
|
|
|
|
<item> <tt/.DEFINE/ style macros may take parameters. While classic macros
|
|
may have empty parameters, this is not true for <tt/.DEFINE/ 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/.DEFINE/ 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.
|
|
|
|
</itemize>
|
|
|
|
Let's look at a few examples to make the advantages and disadvantages
|
|
clear.
|
|
|
|
To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the
|
|
following <tt/.DEFINE/:
|
|
|
|
<tscreen><verb>
|
|
.define EQU =
|
|
|
|
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"
|
|
|
|
; ... and use it
|
|
.asciiz VERSION
|
|
</verb></tscreen>
|
|
|
|
Macros with parameters may also be useful:
|
|
|
|
<tscreen><verb>
|
|
.define DEBUG(message) .out message
|
|
|
|
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:
|
|
|
|
<tscreen><verb>
|
|
.macro message
|
|
.out message
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
(This is an example where a problem can be solved with both macro types).
|
|
|
|
|
|
|
|
<sect>Macro packages
|
|
|
|
<p>
|
|
Using the <tt/.MACPACK/ directive, predefined macro packages may be included
|
|
with just one command. Available macro packages are:
|
|
|
|
<descrip>
|
|
|
|
<tag><tt><idx>generic</idx></tt></tag>
|
|
|
|
This macro package defines macros that are useful in almost any program.
|
|
Currently, two macros are defined:
|
|
|
|
<tscreen><verb>
|
|
.macro add Arg
|
|
clc
|
|
adc Arg
|
|
.endmacro
|
|
|
|
.macro sub Arg
|
|
sec
|
|
sbc Arg
|
|
.endmacro
|
|
</verb></tscreen>
|
|
|
|
|
|
<tag><tt><idx>longbranch</idx></tt></tag>
|
|
|
|
This macro package defines long conditional jumps. They are named like the
|
|
short counterpart but with the 'b' replaced by a 'j'. Here is a sample
|
|
definition for the "<tt/jeq/" macro, the other macros are built using the
|
|
same scheme:
|
|
|
|
<tscreen><verb>
|
|
.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
|
|
jump) and is reachable with a short jump. Otherwise the macro expands to a
|
|
conditional branch with the branch condition inverted, followed by an
|
|
absolute jump to the actual branch target.
|
|
|
|
The package defines the following macros:
|
|
|
|
<tscreen><verb>
|
|
jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc
|
|
</verb></tscreen>
|
|
|
|
</descrip>
|
|
|
|
|
|
<sect>Bugs/Feedback<p>
|
|
|
|
If you have problems using the assembler, if you find any bugs, or if
|
|
you're doing something interesting with the assembler, I would be glad to
|
|
hear from you. Feel free to contact me by email
|
|
(<htmlurl url="mailto:uz@cc65.org" name="uz@cc65.org">).
|
|
|
|
|
|
|
|
<sect>Copyright<p>
|
|
|
|
ca65 (and all cc65 binutils) are (C) Copyright 1998-2000 Ullrich von
|
|
Bassewitz. For usage of the binaries and/or sources the following
|
|
conditions do apply:
|
|
|
|
This software is provided 'as-is', without any expressed or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
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.
|
|
</enum>
|
|
|
|
|
|
|
|
</article>
|
|
|
|
|
|
|