2009-10-17 19:47:06 +00:00
|
|
|
XASM (1)
|
|
|
|
========
|
2013-10-02 11:24:57 +00:00
|
|
|
:doctype: manpage
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
NAME
|
|
|
|
----
|
|
|
|
xasm - 6502 cross-assembler
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
--------
|
|
|
|
*xasm* '[OPTIONS] SOURCE_FILE'
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
-----------
|
|
|
|
*xasm* is a cross-assembler for the 6502 family processors.
|
|
|
|
|
|
|
|
'SOURCE_FILE' is the name of the source file
|
|
|
|
(you may omit the default `.asx` extension).
|
|
|
|
When invoked without any options, *xasm* assembles 'SOURCE_FILE'
|
|
|
|
and writes the result to an object file named 'SOURCE_FILE'
|
|
|
|
with the extension changed to `.obx`.
|
|
|
|
|
|
|
|
OPTIONS
|
|
|
|
-------
|
|
|
|
|
|
|
|
*/c*::
|
|
|
|
Specifies that lines skipped due to a false condition
|
|
|
|
should be included in the listing file.
|
|
|
|
|
|
|
|
[[new_deflabel]]*/d:*'LABEL'='VALUE'::
|
|
|
|
Defines a label.
|
|
|
|
'LABEL' should be a valid label name.
|
|
|
|
'VALUE' may be any expression (may reference to labels defined in source files).
|
|
|
|
You may use several */d* options to define many labels from the command line.
|
|
|
|
|
|
|
|
*/i*::
|
|
|
|
Excludes included files from the listing file.
|
|
|
|
|
|
|
|
*/l*'[:LISTING_FILE]'::
|
|
|
|
Generates listing file.
|
|
|
|
If 'LISTING_FILE' is omitted, the listing filename
|
|
|
|
is 'SOURCE_FILE' with the extension changed to `.lst`.
|
|
|
|
|
|
|
|
[[new_makefile]]*/M*::
|
|
|
|
Prints a rule for use in a `Makefile`.
|
|
|
|
First line of the rule lists 'OBJECT_FILE' as the target of the rule
|
2014-07-20 17:10:41 +00:00
|
|
|
and all source files (including the ones specified with `icl` and `ins` directives)
|
2009-10-17 19:47:06 +00:00
|
|
|
as dependencies. The second line contains the command line with `OBJECT_FILE`
|
|
|
|
replaced by the *make* macro `$@` and `SOURCE_FILE` replaced by the macro `$<`.
|
|
|
|
Dollars in the command line are doubled.
|
2014-07-20 17:10:41 +00:00
|
|
|
Your `make` or shell may require further escaping.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
*/o*':OBJECT_FILE'::
|
|
|
|
Sets output file name.
|
|
|
|
The default is 'SOURCE_FILE' with the extension changed to `.obx`.
|
|
|
|
|
|
|
|
[[new_fullpaths]]*/p*::
|
2013-02-19 16:37:14 +00:00
|
|
|
Prints absolute paths in listing and error messages.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
[[new_quiet]]*/q*::
|
2014-07-20 17:10:41 +00:00
|
|
|
Quiet mode. Prevents *xasm* from printing its banner and compilation summary.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
*/t*'[:LABEL_FILE]'::
|
|
|
|
Generates label table.
|
2014-07-20 17:10:41 +00:00
|
|
|
If 'LABEL_FILE' is omitted then the table is appended at the end of the listing.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
[[new_unlabels]]*/u*::
|
|
|
|
Issues a warning message for each label whose value is unused.
|
|
|
|
|
|
|
|
Alternatively, you may use Unix-style options, for example:
|
|
|
|
|
|
|
|
-----------------------------------------------------------
|
|
|
|
xasm -i -d DEBUG=1 -l listing.lst source.asx
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
|
|
|
SYNTAX
|
|
|
|
------
|
|
|
|
|
|
|
|
Source files should be plain ASCII files.
|
|
|
|
LF, CR, CR/LF and Atari ($9b) line terminators are supported.
|
|
|
|
Labels and instructions are case-insensitive.
|
|
|
|
|
|
|
|
*xasm* is backward compatible with Quick Assembler.
|
|
|
|
To compile QA sources with *xasm*, simply replace ATASCII-specific characters
|
|
|
|
with their integer codes. You also have to update all `OPT` directives,
|
|
|
|
but usually you can simply remove them.
|
|
|
|
|
|
|
|
'Label' is a symbol that represents a signed 32-bit integer.
|
|
|
|
You define a label by putting its name at the beginning of a line
|
|
|
|
(with no spaces before).
|
|
|
|
The label will be assigned the current value of the 'origin counter'
|
|
|
|
(i.e. the address of the compiled instruction),
|
|
|
|
unless you use it with the `EQU` directive where it is assigned
|
2014-07-20 17:10:41 +00:00
|
|
|
the value of the `EQU` argument.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
Instructions and directives must be preceded with some whitespace.
|
|
|
|
Without leading whitespace they are treated as label names.
|
|
|
|
For example:
|
|
|
|
----
|
|
|
|
nop
|
|
|
|
----
|
|
|
|
is a 6502 instruction, whereas
|
|
|
|
----
|
|
|
|
nop
|
|
|
|
----
|
2014-07-20 17:10:41 +00:00
|
|
|
(without leading space) defines a label called `nop`.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
Whole-line comments must start with a semicolon, an asterisk or a pipe,
|
|
|
|
with optional label definition and spaces before.
|
|
|
|
Here are examples of whole-line comments:
|
|
|
|
--------------------
|
|
|
|
; this is a comment
|
|
|
|
* so it is
|
|
|
|
label | and this too
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
[[new_linerep]]
|
|
|
|
Lines with instructions (and selected directives) may be 'repeated'.
|
|
|
|
To assemble a single line several times,
|
|
|
|
precede the repeat count with a colon, for example:
|
|
|
|
-----------------
|
|
|
|
:4 asl @
|
2014-07-20 17:10:41 +00:00
|
|
|
mask_lookup :32 dta $80,$40,$20,$10,8,4,2,1
|
2009-10-17 19:47:06 +00:00
|
|
|
-----------------
|
|
|
|
|
|
|
|
In lines with instructions or directives, a comment starts immediately
|
|
|
|
after the instruction/directive has been successfully parsed.
|
2014-07-20 17:10:41 +00:00
|
|
|
That is, in such lines *xasm* does not require a special character
|
2009-10-17 19:47:06 +00:00
|
|
|
to start a comment.
|
|
|
|
-------------------------------------------------------------
|
|
|
|
lda foo ; this is a comment
|
|
|
|
sta bar this too
|
|
|
|
tax #0 tax has no operand, therefore #0 starts this comment
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
[[new_pairing]]
|
2014-07-20 17:10:41 +00:00
|
|
|
You may put two instructions in one line so they share their operand.
|
2009-10-17 19:47:06 +00:00
|
|
|
For example:
|
|
|
|
------------
|
|
|
|
eor:sta foo
|
|
|
|
------------
|
|
|
|
is equivalent to
|
|
|
|
------------
|
|
|
|
eor foo
|
|
|
|
sta foo
|
|
|
|
------------
|
|
|
|
|
|
|
|
Note that
|
|
|
|
------------
|
|
|
|
lda:tax #0
|
|
|
|
------------
|
|
|
|
is allowed because `#0` is treated as a comment for `tax`.
|
|
|
|
|
|
|
|
EXPRESSIONS
|
|
|
|
-----------
|
|
|
|
Expressions are numbers combined with operators and brackets.
|
|
|
|
You should use square brackets, because parentheses are reserved
|
|
|
|
for 6502 indirect addressing.
|
|
|
|
|
|
|
|
A number is:
|
|
|
|
|
|
|
|
- a 32-bit decimal integer, e.g. `-12345`
|
|
|
|
- a 32-bit hexadecimal integer, e.g. `$abcd`
|
|
|
|
- a 32-bit binary integer, e.g. `%10100101`
|
|
|
|
- an ASCII character, e.g. `'a'` or `"a"`
|
|
|
|
- origin counter: `*`
|
|
|
|
- a hardware register (see below), e.g. `^4e`
|
|
|
|
- [[new_opcode]]an opcode (see below), e.g. `{lda #0}` is `$a9`
|
|
|
|
- [[new_linecnt]]the line repeat counter (see below): `#`
|
|
|
|
|
|
|
|
Abbreviations of Atari hardware registers are provided
|
|
|
|
to save two characters (`$d40e` vs `^4e`)
|
|
|
|
and to facilitate porting software between Atari 8-bit computers
|
|
|
|
and the Atari 5200 console.
|
|
|
|
These are very similar machines, one of the biggest differences
|
|
|
|
is the location of hardware registers.
|
|
|
|
|
|
|
|
[cols="^m,^d,^m,^d",options="header"]
|
|
|
|
|================================================
|
2013-10-02 11:24:57 +00:00
|
|
|
|Syntax|Chip |Value|Value in Atari 5200 mode (`opt g+`)
|
2009-10-17 19:47:06 +00:00
|
|
|
| ^0x |GTIA |$D00x|`$C00x`
|
|
|
|
| ^1x |GTIA |$D01x|`$C01x`
|
|
|
|
| ^2x |POKEY|$D20x|`$E80x`
|
|
|
|
| ^3x |PIA |$D30x|'error (there's no PIA chip)'
|
|
|
|
| ^4x |ANTIC|$D40x|`$D40x`
|
|
|
|
|================================================
|
|
|
|
|
|
|
|
The opcode syntax represents the opcode byte of the instruction inside braces.
|
|
|
|
The operand of the instruction is discarded and is needed only to recognize
|
|
|
|
the addressing mode. The instruction should begin right after the left brace
|
|
|
|
and the right brace should immediately follow the operand 'or' the instruction.
|
|
|
|
[[new_op_op]]You can skip the operand if the addressing mode is fixed.
|
|
|
|
Examples: `{lda #}`, `{jsr}`, `{bne}`, `{jmp ()}`, `{sta a:,x}`.
|
|
|
|
|
|
|
|
You can use the line repeat counter (`#`) in the repeated lines.
|
|
|
|
It counts the iterations starting from zero. Examples:
|
|
|
|
----------------------------------------------------
|
|
|
|
:3 dta # ; generates three bytes: 0, 1, 2.
|
|
|
|
line_lo :192 dta l(screen+40*#)
|
|
|
|
line_hi :192 dta h(screen+40*#)
|
|
|
|
dl :59 dta $4f,a(screen+40*#),0,$4f,a(screen+40*#),0
|
|
|
|
----------------------------------------------------
|
|
|
|
|
|
|
|
The following 'binary operators' are supported:
|
|
|
|
|
|
|
|
- `+` Addition
|
|
|
|
- `-` Subtraction
|
|
|
|
- `*` Multiplication
|
|
|
|
- `/` Division
|
|
|
|
- `%` Remainder
|
|
|
|
- `&` Bitwise AND
|
|
|
|
- `|` Bitwise OR
|
|
|
|
- `^` Bitwise XOR
|
|
|
|
- `<<` Arithmetic shift left
|
|
|
|
- `>>` Arithmetic shift right
|
|
|
|
- `==` Equal
|
|
|
|
- `=` Equal (same as `==`)
|
|
|
|
- `!=` Not equal
|
|
|
|
- `<>` Not equal (same as `!=`)
|
|
|
|
- `<` Less than
|
|
|
|
- `>` Greater than
|
|
|
|
- `<=` Less or equal
|
|
|
|
- `>=` Greater or equal
|
|
|
|
- `&&` Logical AND
|
|
|
|
- `||` Logical OR
|
|
|
|
|
|
|
|
[[new_unary]]
|
|
|
|
The following 'unary operators' are supported:
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
- `+` Plus (no operation)
|
2009-10-17 19:47:06 +00:00
|
|
|
- `-` Minus (changes the sign)
|
|
|
|
- `~` Bitwise NOT (complements all bits)
|
|
|
|
- `!` Logical NOT (changes true to false and vice versa)
|
|
|
|
- `<` Low (extracts the low byte)
|
|
|
|
- `>` High (extracts the high byte)
|
|
|
|
|
|
|
|
The operator precedence is following:
|
|
|
|
|
|
|
|
- first: `[]` (brackets)
|
|
|
|
- `+ - ~ < >` (unary)
|
|
|
|
- `* / % & << >>` (binary)
|
|
|
|
- `+ - | ^` (binary)
|
|
|
|
- `= == <> != < > <= >=` (binary)
|
|
|
|
- `!` (unary)
|
|
|
|
- `&&` (binary)
|
|
|
|
- last: `||` (binary)
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
NOTE: Although the operators are similar to those used in C, C++ and Java,
|
|
|
|
their priorities are different.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
Compare and logical operators assume that zero is false and a non-zero
|
|
|
|
is true. They return 1 for true.
|
|
|
|
|
|
|
|
Expressions are calculated in signed 32-bit arithmetic.
|
|
|
|
"Arithmetic overflow" error signals overflow of the 32-bit range.
|
|
|
|
|
|
|
|
DIRECTIVES
|
|
|
|
----------
|
|
|
|
|
|
|
|
*EQU* - assign value of expression to label::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
----------
|
|
|
|
five equ 5
|
|
|
|
here equ *
|
|
|
|
----------
|
|
|
|
|
|
|
|
[[new_opt]]*OPT* - set assembler options::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
Six options are available:
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
- `F` - fill the space between memory areas with `$FF`
|
|
|
|
- `G` - Atari 5200 mode for hardware register abbreviations
|
|
|
|
- `H` - generate Atari executable headers
|
|
|
|
- `L` - write to the listing
|
|
|
|
- `O` - write to the object file
|
2014-04-30 07:19:49 +00:00
|
|
|
- `U` - warn of unused labels
|
2009-10-17 19:47:06 +00:00
|
|
|
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
You can turn any of these on or off.
|
2014-04-30 07:19:49 +00:00
|
|
|
The default (if no `OPT` specified) is `opt f-g-h+l+o+u+`.
|
2009-10-17 19:47:06 +00:00
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
opt l- listing off
|
|
|
|
opt l+o- listing on, object file off
|
|
|
|
opt f+g+h- useful for Atari 5200 cartridges - raw output, 5200 hw regs
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
*ORG* - change value of the origin counter::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
If Atari executable headers are enabled, you can include an operand prefix:
|
|
|
|
|
|
|
|
- `a:` starts a new block even if it's superfluous
|
|
|
|
because the new address equals the current address.
|
|
|
|
- `f:` is same as `a:`, but additionally generates a double-`$FF` prefix
|
|
|
|
before the new header. This prefix is automatically generated
|
|
|
|
at the beginning of the file (no need to include `f:` in the first `ORG`).
|
2013-10-02 11:24:57 +00:00
|
|
|
|
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
---------------
|
|
|
|
org $600
|
|
|
|
org f:$700
|
|
|
|
table org *+100
|
|
|
|
---------------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
In the latter example `table` points to 100 bytes
|
|
|
|
of uninitialized data (label is assigned with `*`
|
|
|
|
before the `ORG` directive is executed).
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
[[new_orgr]]Starting with version 2.6.0, *xasm* supports code
|
2014-07-20 17:10:41 +00:00
|
|
|
that is relocated at run time. Let's say you want your code
|
2009-10-17 19:47:06 +00:00
|
|
|
to be located on page zero. You can't normally load it directly into this
|
|
|
|
place, so you load it at a different address and then move in your program.
|
|
|
|
`org r:` changes the address that it used for code generation
|
|
|
|
but not the address used for generating Atari executable headers.
|
|
|
|
Example:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
--------------------------------------
|
|
|
|
org $8000
|
|
|
|
ldx #code_length-1
|
|
|
|
mva:rpl code_loaded,x z:code_zpage,x-
|
|
|
|
jmp code_zpage
|
|
|
|
|
|
|
|
code_loaded
|
|
|
|
org r:$30
|
|
|
|
code_zpage
|
|
|
|
jmp * ; ... or something more sensible
|
|
|
|
code_length equ *-code_zpage
|
|
|
|
--------------------------------------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
Note that both `*` and label definitions use the counter used
|
2014-07-20 17:10:41 +00:00
|
|
|
for code generation. There is no direct access to the other counter.
|
|
|
|
You can only calculate it:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
---------------------------------------
|
|
|
|
where_am_i equ *-code_zpage+code_loaded
|
|
|
|
---------------------------------------
|
|
|
|
|
|
|
|
[[new_dta]]*DTA* - define data::
|
|
|
|
|
|
|
|
- integers
|
|
|
|
+
|
|
|
|
--
|
|
|
|
* bytes: `b(200)` or simply `200`
|
|
|
|
* words: `a(10000)`
|
|
|
|
* low bytes of words: `l(511)` (byte 255)
|
|
|
|
* high bytes of words: `h(511)` (byte 1)
|
|
|
|
|
|
|
|
You may enter many expressions in parentheses and combine different types
|
|
|
|
of data in single line, separating things with commas.
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
You may also build a sine lookup table. The syntax is:
|
2009-10-17 19:47:06 +00:00
|
|
|
-------------------------------
|
2014-07-20 17:10:41 +00:00
|
|
|
sin(center,amp,period,first,last)
|
2009-10-17 19:47:06 +00:00
|
|
|
-------------------------------
|
|
|
|
where:
|
|
|
|
|
|
|
|
* `center` is an integer which is added to every sine value
|
|
|
|
* `amp` is the sine amplitude
|
2014-07-20 17:10:41 +00:00
|
|
|
* `period` is the number of values per sine period
|
2009-10-17 19:47:06 +00:00
|
|
|
* `first,last` define the range of sine arguments.
|
2014-07-20 17:10:41 +00:00
|
|
|
They are optional. The default are `0,period-1`.
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
Example:
|
|
|
|
----------------------------
|
|
|
|
dta a(sin(0,1000,256,0,63))
|
|
|
|
----------------------------
|
|
|
|
defines a table of 64 words representing a quarter of sine with the amplitude of 1000.
|
|
|
|
--
|
|
|
|
|
|
|
|
- real numbers: `r(-1.23456e12)`
|
|
|
|
+
|
|
|
|
Real numbers are stored in the 6-byte Atari Floating-Point format.
|
|
|
|
|
|
|
|
- text strings
|
|
|
|
+
|
|
|
|
--
|
|
|
|
* ASCII strings: `c'Text'` or `c"Text"`
|
|
|
|
* ANTIC strings: `d'Text'` or `d"Text"`
|
|
|
|
|
|
|
|
A character string consists of any number of characters surrounded by quotation
|
|
|
|
marks. You can include the quotation marks in the string by doubling them.
|
|
|
|
Placing a `*` character after a string inverts
|
|
|
|
the highest bit in every byte of the string.
|
|
|
|
--
|
|
|
|
+
|
|
|
|
Examples of `DTA`:
|
|
|
|
+
|
|
|
|
------------------------------------------------
|
|
|
|
dta b(1,2),3,a(1000,-1),l(12345,sin(0,127,256))
|
|
|
|
dta d"ANTIC"*,c'It''s a string',$9b
|
|
|
|
------------------------------------------------
|
|
|
|
|
|
|
|
*ICL* - include another source file::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Specifies another file to be included in the assembly as if the contents
|
|
|
|
of the referenced file appeared in place of the `ICL` statement.
|
|
|
|
The included file may contain other `ICL` statements.
|
|
|
|
The `.asx` extension is added if none given.
|
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
-----------------
|
|
|
|
icl 'macros.asx'
|
|
|
|
icl 'lib/fileio'
|
|
|
|
-----------------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
|
|
|
NOTE: for portability, use only relative paths and slash as the separator.
|
2009-10-17 19:47:06 +00:00
|
|
|
This way your sources will compile under Windows and Linux.
|
|
|
|
|
|
|
|
*END* - end assembling file::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
May be used if the source file ends with something which shouldn't
|
2014-07-20 17:10:41 +00:00
|
|
|
be read by *xasm* (e.g. your notes).
|
2009-10-17 19:47:06 +00:00
|
|
|
|
|
|
|
*INS* - insert contents of file::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Copies every byte of the specified file into the object file and updates
|
2014-07-20 17:10:41 +00:00
|
|
|
the origin counter, as if these bytes were written using `DTA`.
|
2009-10-17 19:47:06 +00:00
|
|
|
You may specify a range of the file to insert. The syntax is:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
-----------------------------
|
|
|
|
ins 'file'[,offset[,length]]
|
|
|
|
-----------------------------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
The first byte in a file has the offset of zero.
|
|
|
|
If the offset is negative, it counts from the end of the file.
|
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
-----------------------------------------------
|
|
|
|
ins 'picture.raw'
|
|
|
|
ins 'file',-256 insert last 256 bytes of file
|
|
|
|
ins 'file',10,10 insert bytes 10..19 of file
|
|
|
|
-----------------------------------------------
|
|
|
|
|
|
|
|
*RUN* - set run address in the Atari executable format::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
---------
|
|
|
|
run main
|
|
|
|
---------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
is equivalent to:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
------------
|
|
|
|
org $2e0
|
|
|
|
dta a(main)
|
|
|
|
------------
|
|
|
|
|
|
|
|
*INI* - set init address in the Atari executable format::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Example:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
------------
|
2014-07-20 17:10:41 +00:00
|
|
|
ini showloadingpic
|
2009-10-17 19:47:06 +00:00
|
|
|
------------
|
|
|
|
|
|
|
|
*ERT* - generate error if expression evaluates to true::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Examples:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
-----------------------
|
|
|
|
ert *>$c000
|
|
|
|
ert len1>$ff||len2>$ff
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
[[new_eli]]*IFT* - assemble if expression is true::
|
|
|
|
*ELI* - else if::
|
|
|
|
*ELS* - else::
|
|
|
|
*EIF* - end if::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
With these directives you can construct fragments which
|
|
|
|
are assembled only when a condition is met.
|
|
|
|
Conditional constructions can be nested.
|
|
|
|
Example:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
-------------
|
|
|
|
noscr equ 1
|
|
|
|
widescr equ 1
|
|
|
|
ift noscr
|
|
|
|
lda #0
|
|
|
|
eli widescr
|
|
|
|
lda #$23
|
|
|
|
els
|
|
|
|
lda #$22
|
|
|
|
eif
|
|
|
|
sta $22f
|
|
|
|
-------------
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2014-07-20 17:10:41 +00:00
|
|
|
NOTE: The above example may be rewritten using the 'repeat line' feature:
|
2013-10-02 11:24:57 +00:00
|
|
|
+
|
2009-10-17 19:47:06 +00:00
|
|
|
--------------------------
|
|
|
|
noscr equ 1
|
|
|
|
widescr equ 1
|
|
|
|
:noscr lda #0
|
|
|
|
:!noscr&&widescr lda #$23
|
|
|
|
:!noscr&&!widescr lda #$22
|
|
|
|
sta $22f
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
PSEUDO COMMANDS
|
|
|
|
---------------
|
|
|
|
'Pseudo commands' are built-in macros. There are no user-defined macros in *xasm*.
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
*ADD* - add without carry::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
If you have ever programmed a 6502, you must have noticed that you had
|
|
|
|
to use a `CLC` before `ADC` for every simple addition.
|
|
|
|
+
|
|
|
|
*xasm* can do it for you. `ADD` replaces two instructions: `CLC` and `ADC`.
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
*SUB* - subtract::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
It is `SEC` and `SBC`.
|
|
|
|
|
|
|
|
[[new_repskip]]*RCC, RCS, REQ, RMI, RNE, RPL, RVC, RVS* - conditional repeat::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
These are branches to the previous instruction.
|
|
|
|
They take no operand, because the branch target is the address
|
|
|
|
of the previously assembled instruction or pseudo command.
|
|
|
|
Example:
|
|
|
|
+
|
|
|
|
-----------------------
|
|
|
|
ldx #0
|
|
|
|
mva:rne $500,x $600,x+
|
|
|
|
-----------------------
|
|
|
|
+
|
|
|
|
The above code copies a 256-byte memory block from $500 to $600.
|
|
|
|
Here is the same written with standard 6502 commands only:
|
|
|
|
+
|
|
|
|
--------------------
|
|
|
|
ldx #0
|
|
|
|
copy_loop lda $500,x
|
|
|
|
sta $600,x
|
|
|
|
inx
|
|
|
|
bne copy_loop
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
*SCC, SCS, SEQ, SMI, SNE, SPL, SVC, SVS* - conditional skip::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
These are branches over the next instruction. No operand is required,
|
|
|
|
because the target is the address of the instruction following
|
|
|
|
the next instruction.
|
|
|
|
Example:
|
|
|
|
+
|
|
|
|
--------------
|
|
|
|
lda #40
|
|
|
|
add:sta ptr
|
|
|
|
scc:inc ptr+1
|
|
|
|
--------------
|
|
|
|
+
|
|
|
|
In the above example the 16-bit variable `ptr` is incremented by 40.
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
*JCC, JCS, JEQ, JMI, JNE, JPL, JVC, JVS* - conditional jump::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
These are long branches. While standard branches (such as `BNE`)
|
|
|
|
have range of -128..+127, these jumps have range of 64 kB.
|
|
|
|
For example:
|
|
|
|
+
|
|
|
|
---------
|
|
|
|
jne dest
|
|
|
|
---------
|
|
|
|
+
|
|
|
|
is equivalent to:
|
|
|
|
+
|
|
|
|
-------------
|
|
|
|
seq:jmp dest
|
|
|
|
-------------
|
|
|
|
|
|
|
|
*INW* - increment word::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Increments a 16-bit word in the memory.
|
|
|
|
Example:
|
|
|
|
+
|
|
|
|
---------
|
|
|
|
inw dest
|
|
|
|
---------
|
|
|
|
+
|
|
|
|
is equivalent to:
|
|
|
|
+
|
|
|
|
---------------
|
|
|
|
inc dest
|
|
|
|
sne:inc dest+1
|
|
|
|
---------------
|
|
|
|
|
|
|
|
*MVA, MVX, MVY* - move byte using accumulator, X or Y::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Each of these pseudo commands requires two operands
|
|
|
|
and substitutes two commands:
|
|
|
|
+
|
|
|
|
----------------------------------------
|
|
|
|
mva source dest = lda source : sta dest
|
|
|
|
mvx source dest = ldx source : stx dest
|
|
|
|
mvy source dest = ldy source : sty dest
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
[[new_mwinde]]*MWA, MWX, MWY* - move word using accumulator, X or Y::
|
2013-10-02 11:24:57 +00:00
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
These pseudo commands require two operands and are combinations of two `MVA`/`MVX`/`MWY`:
|
2009-10-17 19:47:06 +00:00
|
|
|
one to move the low byte, and the other to move the high byte.
|
2014-07-20 17:10:41 +00:00
|
|
|
You can't use indirect nor pseudo addressing mode with `MWA`/`MWX`/`MWY`.
|
|
|
|
Destination must be an absolute or zeropage address, optionally indexed.
|
|
|
|
When source is also an absolute or zeropage address, an `mwa source dest` expands to:
|
2009-10-17 19:47:06 +00:00
|
|
|
+
|
|
|
|
--------------------
|
2014-07-20 17:10:41 +00:00
|
|
|
mva source dest
|
|
|
|
mva source+1 dest+1
|
2009-10-17 19:47:06 +00:00
|
|
|
--------------------
|
|
|
|
+
|
2014-07-20 17:10:41 +00:00
|
|
|
When source is an immediate value, an `mwa #immed dest` expands to:
|
2009-10-17 19:47:06 +00:00
|
|
|
+
|
|
|
|
------------------
|
2014-07-20 17:10:41 +00:00
|
|
|
mva <immed dest
|
|
|
|
mva >immed dest+1
|
2009-10-17 19:47:06 +00:00
|
|
|
------------------
|
|
|
|
+
|
|
|
|
When `<immed` equals `>immed` and `immed` is not forward-referenced,
|
2014-07-20 17:10:41 +00:00
|
|
|
*xasm* skips the second `LDA`, generating the following code:
|
2009-10-17 19:47:06 +00:00
|
|
|
+
|
|
|
|
----------------
|
2014-07-20 17:10:41 +00:00
|
|
|
mva <immed dest
|
|
|
|
sta dest+1
|
2009-10-17 19:47:06 +00:00
|
|
|
----------------
|
|
|
|
+
|
|
|
|
If possible, `MWX` and `MWY` use increment/decrement commands.
|
|
|
|
For example, `mwx #1 dest` expands to:
|
|
|
|
+
|
|
|
|
-----------
|
|
|
|
ldx #1
|
|
|
|
stx dest
|
|
|
|
dex
|
|
|
|
stx dest+1
|
|
|
|
-----------
|
|
|
|
|
|
|
|
ADDRESSING MODES
|
|
|
|
----------------
|
|
|
|
|
|
|
|
All addressing modes are entered in the standard 6502 convention
|
|
|
|
except for the accumulator addressing mode,
|
|
|
|
which should be marked with the `@` character (as in Quick Assembler).
|
|
|
|
|
|
|
|
For Quick Assembler compatibility, there are two extra immediate
|
|
|
|
addressing modes: `<` and `>`, which use the low/high byte of a 16-bit word constant.
|
|
|
|
Unlike in Quick Assembler, you can alternatively use
|
|
|
|
the more common syntax: `#<` and `#>`.
|
|
|
|
Note the difference:
|
|
|
|
-------------------------------
|
|
|
|
lda >$ff+5 ; loads 1 (>$104)
|
|
|
|
lda #>$ff+5 ; loads 5 (0+5)
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
You can explicitly specify absolute (`a:`) and zero-page (`z:`) addressing modes.
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
--------------------------------------
|
|
|
|
nop
|
|
|
|
asl @
|
|
|
|
lda >$1234 assembles to lda #$12
|
|
|
|
lda $100,x
|
|
|
|
lda 0 zero-page (8-bit address)
|
|
|
|
lda a:0 absolute (16-bit address)
|
|
|
|
jmp ($0a)
|
|
|
|
lda ($80),y
|
|
|
|
--------------------------------------
|
|
|
|
|
|
|
|
[[new_adrmodes]]
|
|
|
|
There are 'pseudo addressing modes', which are similar to pseudo commands.
|
|
|
|
You may use them just like standard addressing modes in all 6502 commands
|
|
|
|
and pseudo commands, except for `MWA`, `MWX` and `MWY`:
|
|
|
|
------------------------------------------
|
|
|
|
cmd a,x+ = cmd a,x : inx
|
|
|
|
cmd a,x- = cmd a,x : dex
|
|
|
|
cmd a,y+ = cmd a,y : iny
|
|
|
|
cmd a,y- = cmd a,y : dey
|
|
|
|
cmd (z),y+ = cmd (z),y : iny
|
|
|
|
cmd (z),y- = cmd (z),y : dey
|
|
|
|
cmd (z,0) = ldx #0 : cmd (z,x)
|
|
|
|
cmd (z),0 = ldy #0 : cmd (z),y
|
|
|
|
cmd (z),0+ = ldy #0 : cmd (z),y : iny
|
|
|
|
cmd (z),0- = ldy #0 : cmd (z),y : dey
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
HISTORY
|
|
|
|
-------
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
Version 3.1.0 (2014-07-20)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- OS X, Ubuntu and Fedora distributions
|
|
|
|
- `INS` can be repeated (suggested by Marek Pavlik) and taken "opcode" of
|
|
|
|
- `OPT U-` disables <<new_unlabels,*/u*>> unused label warnings
|
|
|
|
(suggested by Marek Pavlik)
|
2016-01-03 10:21:17 +00:00
|
|
|
- if the file to be included cannot be opened, report error in the `ICL` line
|
2014-07-20 17:10:41 +00:00
|
|
|
(suggested by Peter Dell)
|
|
|
|
- removed duplicate filenames for <<new_makefile,*/M*>>
|
|
|
|
- implemented <<new_fullpaths,*/p*>> outside Windows
|
|
|
|
- source code updated from D1 to D2
|
|
|
|
- project moved to GitHub
|
|
|
|
|
2009-10-17 19:47:06 +00:00
|
|
|
Version 3.0.2 (2009-10-17)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed "Branch out of range" error message - was overstated by 256 bytes
|
|
|
|
for backward branches
|
2014-07-20 17:10:41 +00:00
|
|
|
- <<new_makefile,new command-line option */M* prints a Makefile rule>>
|
2009-10-17 19:47:06 +00:00
|
|
|
- command-line options are now case-insensitive
|
|
|
|
- on Windows error messages are printed in red, warnings in yellow
|
|
|
|
|
|
|
|
Version 3.0.1 (2007-04-22)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed a bug in `OPT H-` mode
|
|
|
|
- made *xasm* compilable with the latest D compiler v1.010
|
|
|
|
(there were incompatible changes in the D language and library)
|
|
|
|
|
|
|
|
Version 3.0.0 (2005-05-22)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- rewritten from the x86 assembly language to the
|
2014-07-20 17:10:41 +00:00
|
|
|
http://dlang.org/[D programming language] - Linux version
|
2009-10-17 19:47:06 +00:00
|
|
|
is now available and DOS is no longer supported
|
|
|
|
- no limits for line length, number of `ICLs`, `ORGs`,`IFTs` and labels
|
|
|
|
- Unix-style command-line options are supported
|
|
|
|
- */e* option is no longer supported
|
|
|
|
- the label table is now sorted alphabetically
|
|
|
|
|
|
|
|
Version 2.6.1 (2005-05-21)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- no more "Arithmetic overflow" and "Division by zero" errors for correct
|
|
|
|
use of forward-referenced labels (bug found by Marcin Lewandowski)
|
|
|
|
- an error was reported in the following correct code:
|
|
|
|
+
|
|
|
|
---------
|
|
|
|
ift 0
|
|
|
|
foo equ 1
|
|
|
|
ift foo
|
|
|
|
eif
|
|
|
|
eif
|
|
|
|
---------
|
|
|
|
+
|
|
|
|
(bug found by Adrian Matoga)
|
|
|
|
|
|
|
|
- errors for non-existing `INC @` and `DEC @`
|
|
|
|
- negative numbers fixed in the listing
|
|
|
|
|
|
|
|
Version 2.6.0 (2005-02-07)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- long file names are supported under Windows
|
|
|
|
- <<new_orgr,support for code relocated at runtime>>
|
|
|
|
- <<new_linecnt,line repeat counter>>
|
|
|
|
- label values are now 32-bit, not just 17-bit
|
|
|
|
- command-line options */n* and */s* are no longer supported
|
|
|
|
- fatal I/O errors (such as floppy not ready) no longer print the annoying
|
|
|
|
"Abort, Retry, Ignore" message
|
|
|
|
|
|
|
|
Version 2.5.2 (2002-10-03)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- version 2.5.1 broke Unix EOLs - fixed
|
|
|
|
- version 2.5.1 omitted all blank/comment/label lines, unless */c* was used
|
|
|
|
|
|
|
|
Version 2.5.1 (2002-08-21)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed assembling sources with Atari EOLs
|
|
|
|
- blank/comment/label lines in false conditionals are now correctly omitted
|
|
|
|
in listing
|
|
|
|
|
|
|
|
Version 2.5 (2002-07-08)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed another bug, very similar to the previous one, e.g.
|
|
|
|
+
|
|
|
|
----------
|
|
|
|
ift 0
|
|
|
|
:label nop
|
|
|
|
eif
|
|
|
|
----------
|
|
|
|
+
|
|
|
|
reported "Label not defined before" error for the repeat count
|
|
|
|
|
|
|
|
- <<new_opt,`OPT F+` causes `ORG` to fill the space
|
|
|
|
between the old and the new location with `$FFs`>>
|
|
|
|
- <<new_opt,`OPT G+` enables Atari 5200 mode for hardware
|
|
|
|
register abbreviations>>
|
|
|
|
|
|
|
|
Version 2.4.1 (2002-06-27)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed a bug related to label definitions in conditionally skipped code,
|
|
|
|
e.g.
|
|
|
|
+
|
|
|
|
----------
|
|
|
|
ift 0
|
|
|
|
label
|
|
|
|
eif
|
|
|
|
----------
|
|
|
|
+
|
|
|
|
reported "No ORG specified" error for the label definition
|
|
|
|
|
|
|
|
Version 2.4 (2002-05-22)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed incorrect unary operator precedence
|
|
|
|
- fixed wrong label value after a skip pseudo command
|
|
|
|
- the assembler is .EXE (.COM caused problems with DJGPP *make* due
|
|
|
|
to a bug in the DJGPP runtime)
|
|
|
|
- the assembler executable is not compressed (so it occupies less space in the ZIP)
|
|
|
|
- improved command-line parsing: options may be used before source file name,
|
|
|
|
tab character is a valid separator, slash may be used as a directory separator
|
|
|
|
- error and warning messages are written to stderr, not stdout
|
|
|
|
- added `==` (equals) operator, which is equivalent to `=`,
|
|
|
|
but more natural for C/C++/Java programmers
|
|
|
|
- <<new_deflabel,added `/d:label=value` option: define a label>>
|
|
|
|
- <<new_fullpaths,added `/p` option: print full paths
|
|
|
|
in listing and error messages>>
|
|
|
|
- <<new_quiet,added `/q` option: quiet mode>>
|
|
|
|
- <<new_unlabels,added `/u` option: warn of unused labels>>
|
|
|
|
- <<new_opt,writing to the object file may be suppressed with `OPT O-`>>
|
|
|
|
- <<new_eli,added `ELI` (else if) directive>>
|
|
|
|
- <<new_mwinde,`MWX` and `MWY` may use `INX`/`DEX` and `INY`/`DEY`,
|
|
|
|
respectively, for generating shorter code>>
|
|
|
|
|
|
|
|
Version 2.3 (2002-02-10)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed double skip (e.g. `SCC:SNE`)
|
|
|
|
- fixed real numbers with two-digit exponent
|
|
|
|
- trailing spaces are trimmed from listing lines
|
|
|
|
- label definitions allowed in blank, comment and repeated lines
|
|
|
|
- <<new_unary,unary operators>>
|
|
|
|
- <<new_dta,`DTA` implied byte mode>>
|
|
|
|
- <<new_op_op,operand can be skipped for some opcodes>>
|
|
|
|
|
|
|
|
Version 2.2 (1999-09-10)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed invalid opcodes of absolute `CPX` and `CPY`
|
|
|
|
- fixed: addressing mode not checked for branch commands
|
|
|
|
- fixed `ICL` in last line
|
|
|
|
- fixed `OPT H-H+`
|
|
|
|
- fixed first `ORG *`
|
|
|
|
- no need to set origin counter until it's used
|
|
|
|
- allow Unix, Macintosh and Atari EOLs
|
|
|
|
- value of 'true' changed to 1
|
|
|
|
- command-line option to set environment variables on error
|
|
|
|
- commane-line option to assemble only if source is newer than object file
|
|
|
|
- <<new_opcode,opcode extracting>>
|
|
|
|
- <<new_linerep,repeat line>>
|
|
|
|
- <<new_pairing,two instructions in line>>
|
|
|
|
- <<new_repskip,conditional repeat and skip pseudo commands>>
|
|
|
|
- <<new_adrmodes,`(),0+` and `(),0-` pseudo addressing modes>>
|
|
|
|
|
|
|
|
Version 2.0 (1998-11-12)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- fixed: name of object file was truncated
|
|
|
|
- fixed forward references in `EQU` and `DTA`
|
|
|
|
- fixed hex numbers
|
|
|
|
- `.OBX` is now the default extension for the object file
|
|
|
|
- options (command-line switches and `OPT`)
|
|
|
|
- listing
|
|
|
|
- label table
|
|
|
|
- conditional assembly
|
|
|
|
- user errors (`ERT`)
|
|
|
|
- warnings
|
|
|
|
- 6 new pseudo commands (memory-to-memory move)
|
|
|
|
- 8 pseudo addressing modes
|
|
|
|
- indirect conditional jumps
|
|
|
|
- Atari floating-point numbers
|
|
|
|
- object file headers optimization
|
|
|
|
- improved expressions - 19 operators and brackets, 32-bit arithmetic
|
|
|
|
- improved signed numbers
|
|
|
|
- improved `INS`: inserting specified part of file
|
|
|
|
|
|
|
|
Version 1.2 (1998-08-14)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
- first release
|
|
|
|
|
|
|
|
AUTHOR
|
|
|
|
------
|
|
|
|
Piotr Fusik <fox@scene.pl>
|
|
|
|
|
|
|
|
SEE ALSO
|
|
|
|
--------
|
|
|
|
|
2014-07-20 17:10:41 +00:00
|
|
|
Website: https://github.com/pfusik/xasm[]
|