1
0
mirror of https://github.com/pfusik/xasm.git synced 2024-11-01 00:05:53 +00:00

xasm 3.0.2 release.

This commit is contained in:
Piotr Fusik 2009-10-17 21:47:06 +02:00
parent fa25272ccd
commit 034b95ea83
7 changed files with 1084 additions and 944 deletions

53
Makefile Normal file
View File

@ -0,0 +1,53 @@
VERSION = 3.0.2
ASCIIDOC = asciidoc -o $@ -a doctime
ASCIIDOC_POSTPROCESS = perl -pi.bak -e "s/527bbd;/20a0a0;/;END{unlink '$@.bak'}" $@
ASCIIDOC_VALIDATE = xmllint --valid --noout --nonet $@
RM = rm -f
ZIP = 7z a -mx=9 -tzip $@
all: xasm.exe xasm.html
xasm.exe: xasm.d
dmd -O -release $<
xasm.html: xasm.1.txt
$(ASCIIDOC) -d manpage $<
$(ASCIIDOC_POSTPROCESS)
$(ASCIIDOC_VALIDATE)
dist: xasmpage-$(VERSION).zip
xasmpage-$(VERSION).zip: xasm261.zip xasm-$(VERSION)-src.zip xasm-$(VERSION)-windows.zip inflate6502.zip index.html inflate.html scite.png
$(RM) $@
$(ZIP) $^
xasm-$(VERSION)-src.zip: xasm.d Makefile xasm.1.txt
$(RM) $@
$(ZIP) $^
xasm-$(VERSION)-windows.zip: xasm.exe xasm.html xasm.properties
$(RM) $@
$(ZIP) $^
inflate6502.zip: inflate.asx gzip2deflate.c gzip2deflate.exe
$(RM) $@
$(ZIP) $^
gzip2deflate.exe: gzip2deflate.c
mingw32-gcc -s -O2 -Wall -o $@ $<
index.html: index.txt
$(ASCIIDOC) $<
$(ASCIIDOC_POSTPROCESS)
$(ASCIIDOC_VALIDATE)
inflate.html: inflate.txt
$(ASCIIDOC) $<
$(ASCIIDOC_POSTPROCESS)
$(ASCIIDOC_VALIDATE)
clean:
$(RM) xasmpage-$(VERSION).zip xasm-$(VERSION)-src.zip xasm-$(VERSION)-windows.zip xasm.exe xasm.html inflate6502.zip gzip2deflate.exe index.html inflate.html
.DELETE_ON_ERROR:

View File

@ -1,117 +0,0 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The source code and object code supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>xasm</title>
<meta name="Description" content="xasm is a 6502 cross-assembler for Windows and Linux." />
<meta name="Keywords" content="xasm,6502,cross-assembler,atari,8-bit" />
<meta name="Author" content="Piotr Fusik" />
<style type="text/css">
body { background-color: #f8f8f8; color: black; font-family: sans-serif; }
h1 { color: #20a0a0; border-bottom: solid 3px #d0d0d0; }
h2 { color: #20a0a0; border-bottom: solid 2px #d0d0d0; }
</style>
</head>
<body>
<h1>xasm - 6502 cross-assembler</h1>
<p>xasm is a free tool for programming old 8-bit computers based on the 6502 processor.</p>
<h2>History</h2>
<p>First version of xasm was written in 1998. I needed a cross-assembler
that could understand the syntax of Quick Assembler
which I used for 8-bit Atari programming before I got a PC.
Initially xasm supported the syntax of QA and nothing more.
I quickly realized that I could extend the syntax to make it more expressive.
This led to xasm 2.0, still in 1998. I added some more features
next year. In 2002 I released many versions which contained
mostly bugfixes. In 2005 there were some minor enhancements and bug fixes,
as well as the whole assembler was rewritten from the x86 assembly language
it was initially written in to the
<a href="http://www.digitalmars.com/d">D programming language</a>.
The rewrite introduced a bug, hopefully fixed in version 3.0.1
released 22nd April 2007.</p>
<h2>Syntax</h2>
<p>6502 assembler code is usually full of LDA, STA, LDA, STA sequences.
With xasm you can use MVA as a shortcut for LDA/STA pair
or even MWA for 16-bit transfers. You can avoid defining labels
when you need short jumps, thanks to conditional skip
and repeat pseudo-instructions. You can put two instructions
that share their argument in one line.
These are just some of the features that help you program
in a more concise way. Let's look at typical 6502 code
(which is valid in xasm):</p>
<pre>
lda #&lt;dest
sta ptr
lda #&gt;dest
sta ptr+1
ldx #192
do_line
ldy #39
do_byte
lda pattern,y
sta (ptr),y
dey
bpl do_byte
lda #40
clc
adc ptr
sta ptr
bcc skip
inc ptr+1
skip
dex
bne do_line
</pre>
<p>Using xasm features this code can be rewritten to:</p>
<pre>
mwa #dest ptr
ldx #192
do_line
ldy #39
mva:rpl pattern,y (ptr),y-
lda #40
add:sta ptr
scc:inc ptr+1
dex:bne do_line
</pre>
<h2>Usage</h2>
<p>xasm is a command-line tool so you additionally need a general-purpose text editor.
I use <a href="http://www.scintilla.org/SciTE.html">SciTE</a>.
Syntax highlighting definition for it is included with xasm.
To install it, copy <em>xasm.properties</em> to the SciTE directory,
select <em>Options / Open Global Options File</em>, type <kbd>import xasm</kbd>
at the end and save the global configuration file.</p>
<p><img src="scite.png" alt="xasm code in SciTE" /></p>
<h2>Download</h2>
<ul>
<li><a href="xasm-3.0.1-win32.zip">xasm 3.0.1 for Windows</a></li>
<li><a href="xasm-3.0.1-src.zip">xasm 3.0.1 source code</a></li>
<li><a href="xasm261.zip">xasm 2.6.1 for DOS/Windows</a></li>
</ul>
<p>For other systems, such as GNU/Linux and MacOS X, install the latest D compiler
and compile xasm from source code.</p>
<h2>Inflate</h2>
<p>Need a good decompression routine for 6502?
See my <a href="inflate.html">inflate routine</a>.</p>
<h2>Links</h2>
<ul>
<li><a href="http://atari800.sourceforge.net/">Atari800 emulator</a></li>
<li><a href="http://sources.pigwa.net/">Atari XL/XE Source Archive</a></li>
<li><a href="http://www.cc65.org/">cc65 cross-compiler</a></li>
<li><a href="http://epi.atari8.info/hcasm.php">HardCore Assembler</a></li>
<li><a href="http://mads.atari8.info/">Mad-Assembler</a></li>
</ul>
</body>
</html>

112
www/index.txt Normal file
View File

@ -0,0 +1,112 @@
xasm - 6502 cross-assembler
===========================
xasm is a free tool for programming
http://en.wikipedia.org/wiki/Atari_8-bit_family[Atari 8-bit family computers].
History
-------
First version of xasm was written in 1998. I needed a cross-assembler
that could understand the syntax of Quick Assembler
which I used for 8-bit Atari programming before I got a PC.
Initially xasm supported the syntax of QA and nothing more.
I quickly realized that I could extend the syntax to make it more expressive.
This led to xasm 2.0, still in 1998. I added some more features
next year. In 2002 I released many versions which contained
mostly bugfixes. In 2005 there were some minor enhancements and bug fixes,
as well as the whole assembler was rewritten from the x86 assembly language
it was initially written in to the http://www.digitalmars.com/d/[D programming language].
Current version 3.0.2 was released 17th October 2009.
Syntax
------
6502 assembler code is usually full of LDA, STA, LDA, STA sequences.
With xasm you can use MVA as a shortcut for LDA/STA pair
or even MWA for 16-bit transfers. You can avoid defining labels
when you need short jumps, thanks to conditional skip
and repeat pseudo-instructions. You can put two instructions
that share their argument in one line.
These are just some of the features that help you program
in a more concise way. Let's look at typical 6502 code
(which is also valid in xasm):
-----------------------------
lda #<dest
sta ptr
lda #>dest
sta ptr+1
ldx #192
do_line
ldy #39
do_byte
lda pattern,y
sta (ptr),y
dey
bpl do_byte
lda #40
clc
adc ptr
sta ptr
bcc skip
inc ptr+1
skip
dex
bne do_line
-----------------------------
Using xasm's features this code can be rewritten to:
-----------------------------
mwa #dest ptr
ldx #192
do_line
ldy #39
mva:rpl pattern,y (ptr),y-
lda #40
add:sta ptr
scc:inc ptr+1
dex:bne do_line
-----------------------------
Usage
-----
xasm is a command-line tool.
Therefore you additionally need a programmer's text editor.
I use http://www.scintilla.org/SciTE.html[SciTE].
Syntax highlighting definition for it is included with xasm.
To install it, copy `xasm.properties` to the SciTE directory,
select _Options / Open Global Options File_, type `import xasm`
at the end and save the global configuration file.
image::scite.png[xasm code in SciTE]
Download
--------
- link:xasm-3.0.2-windows.zip[xasm 3.0.2 for Windows]
- link:xasm-3.0.2-src.zip[xasm 3.0.2 source code]
- link:xasm261.zip[xasm 2.6.1 for DOS]
For other systems, such as GNU/Linux and MacOS X, install a D 1.x compiler
and compile xasm from source code.
Inflate
-------
Do you need a good decompression routine for 6502?
See my link:inflate.html[inflate routine].
Links
-----
- http://atari800.sourceforge.net/[Atari800 emulator] - portable emulator of Atari 8-bit computers
- http://sources.pigwa.net/[Atari XL/XE Source Archive] - source code of Atari demos, utilities and games
- http://www.cc65.org/[cc65] - C cross-compiler targeting 6502-based systems
- http://epi.atari8.info/hcasm.php[HardCore Assembler] - 6502/65816 cross-assembler, partially supporting xasm's syntax
- http://mads.atari8.info/[MADS] - another 6502/65816 cross-assembler, partially supporting xasm's syntax
- http://wudsn.com/[WUDSN IDE] - Eclipse plugin, front-end to several 6502 cross-assemblers including xasm

825
xasm.1.txt Normal file
View File

@ -0,0 +1,825 @@
XASM (1)
========
Piotr Fusik <fox@scene.pl>
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
and all source files (including the ones specified by `icl` and `ins` directives)
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.
Your `make` or shell may require more escaping.
*/o*':OBJECT_FILE'::
Sets output file name.
The default is 'SOURCE_FILE' with the extension changed to `.obx`.
[[new_fullpaths]]*/p*::
Prints fully qualified file names in listing and error messages.
This option works only on Windows and is silently ignored on other platforms.
[[new_quiet]]*/q*::
Quiet mode. Prevents *xasm* from printing the logo and the summary.
*/t*'[:LABEL_FILE]'::
Generates label table.
If 'LABEL_FILE' is omitted then the table is appended to the listing.
[[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
the value of the argument.
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
----
defines a label called `nop`.
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 @
table :32*5 dta 5
-----------------
In lines with instructions or directives, a comment starts immediately
after the instruction/directive has been successfully parsed.
That is, in these lines *xasm* does not require a special character
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]]
You may put two instructions in one line so they share the operand.
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"]
|================================================
|Syntax|Chip |Value|Value (Atari 5200 mode `opt g+`)
| ^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:
- `+` Plus (does nothing)
- `-` 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)
Although the operators are similar to those used in C, C++ and Java,
their priorities are different than in these languages.
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::
Examples:
----------
five equ 5
here equ *
----------
[[new_opt]]*OPT* - set assembler options::
Five options are available:
- `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
You can turn any of these on or off.
The default (if no `OPT` specified) is `opt f-g-h+l+o+`.
Examples:
------------------------------------------------------------------------------
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::
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`).
Examples:
---------------
org $600
org f:$700
table org *+100
---------------
In the latter example `table` points to 100 bytes
of uninitialized data (label is assigned with `*`
before the `ORG` directive is executed).
[[new_orgr]]Starting with version 2.6.0, *xasm* supports code
that is relocated in the memory at runtime. Let's say you want your code
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:
--------------------------------------
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
--------------------------------------
Note that both `*` and label definitions use the counter used
for code generation. There is no direct access to the other counter,
because I think this is not useful. If you really need it, you can
always type something like:
---------------------------------------
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.
You may also define a sine lookup table. The syntax is:
-------------------------------
sin(center,amp,size,first,last)
-------------------------------
where:
* `center` is an integer which is added to every sine value
* `amp` is the sine amplitude
* `size` is the sine period
* `first,last` define the range of sine arguments.
They are optional. The default are `0,size-1`.
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::
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:
-----------------
icl 'macros.asx'
icl 'lib/fileio'
-----------------
Note: for portability, use only relative paths and slash as the separator.
This way your sources will compile under Windows and Linux.
*END* - end assembling file::
May be used if the source file ends with something which shouldn't
be read by *xasm* (e.g. your notes). At the end of file it's optional.
*INS* - insert contents of file::
Copies every byte of the specified file into the object file and updates
the origin counter, as if these bytes were defined with `DTA`.
You may specify a range of the file to insert. The syntax is:
-----------------------------
ins 'file'[,offset[,length]]
-----------------------------
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:
-----------------------------------------------
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::
---------
run main
---------
is equivalent to:
------------
org $2e0
dta a(main)
------------
*INI* - set init address in the Atari executable format::
Example:
------------
ini showpic
------------
*ERT* - generate error if expression evaluates to true::
Examples:
-----------------------
ert *>$c000
ert len1>$ff||len2>$ff
-----------------------
[[new_eli]]*IFT* - assemble if expression is true::
*ELI* - else if::
*ELS* - else::
*EIF* - end if::
With these directives you can construct fragments which
are assembled only when a condition is met.
Conditional constructions can be nested.
Example:
-------------
noscr equ 1
widescr equ 1
ift noscr
lda #0
eli widescr
lda #$23
els
lda #$22
eif
sta $22f
-------------
Note: the above example may be rewritten using the 'repeat line' feature:
--------------------------
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*.
*ADD* - addition without carry::
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`.
*SUB* - subtraction::
It is `SEC` and `SBC`.
[[new_repskip]]*RCC, RCS, REQ, RMI, RNE, RPL, RVC, RVS* - conditional repeat::
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::
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.
*JCC, JCS, JEQ, JMI, JNE, JPL, JVC, JVS* - conditional jumps::
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::
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::
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::
These pseudo commands require two operands and are combinations of two `MV*`'s:
one to move the low byte, and the other to move the high byte.
You can't use indirect nor pseudo addressing mode with `MW*`.
Destination must be an absolute address, optionally indexed.
When source is also an absolute address, an `mw* source dest` expands to:
+
--------------------
mv* source dest
mv* source+1 dest+1
--------------------
+
When source is an immediate value, an `mw* #immed dest` expands to:
+
------------------
mv* <immed dest
mv* >immed dest+1
------------------
+
When `<immed` equals `>immed` and `immed` is not forward-referenced,
*xasm* skips the second `LD*`:
+
----------------
mv* <immed dest
st* dest+1
----------------
+
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
-------
Version 3.0.2 (2009-10-17)
~~~~~~~~~~~~~~~~~~~~~~~~~~
- fixed "Branch out of range" error message - was overstated by 256 bytes
for backward branches
- <<new_makefile,new command-line option */M* prints Makefile rule>>
- 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
http://www.digitalmars.com/d[D programming language] - Linux version
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
--------
Website: http://xasm.atari.org[]

111
xasm.d
View File

@ -1,5 +1,20 @@
// xasm 3.0.1 by Piotr Fusik <fox@scene.pl>
// xasm 3.0.2 by Piotr Fusik <fox@scene.pl>
// http://xasm.atari.org
// Can be compiled with DMD v1.030.
// Poetic License:
//
// This work 'as-is' we provide.
// No warranty express or implied.
// We've done our best,
// to debug and test.
// Liability for damages denied.
//
// Permission is granted hereby,
// to copy, share, and modify.
// Use as is fit,
// free or for profit.
// These rights, on this notice, rely.
import std.math;
import std.stream;
@ -7,8 +22,10 @@ import std.cstream;
import std.string;
version (Windows) {
import std.c.windows.windows;
extern (Windows) export int GetFullPathNameA(char* lpFileName, int nBufferLength, char* lpBuffer, char** lpFilePart);
extern (Windows) HANDLE GetStdHandle(DWORD nStdHandle);
char[] getFullPath(char[] filename) {
char[260] fullPath;
@ -31,7 +48,7 @@ version (Windows) {
const char[] OPTION_P_DESC = "Ignored for compatibility";
}
const char[] TITLE = "xasm 3.0.1";
const char[] TITLE = "xasm 3.0.2";
char[] sourceFilename = null;
@ -41,6 +58,10 @@ char[][26] optionParameters;
char[][] commandLineDefinitions = null;
char[] makeTarget = null;
char[] makeSources = "";
int exitCode = 0;
int totalLines;
@ -212,14 +233,26 @@ bit getOption(char letter) {
return options[letter - 'a'];
}
void warning(char[] msg) {
void warning(char[] msg, bool error = false) {
dout.flush();
version (Windows) {
HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(h, &csbi);
SetConsoleTextAttribute(h, (csbi.wAttributes & ~0xf) | (error ? 12 : 14));
}
if (line !is null) {
derr.printf("%.*s\n", line);
}
derr.printf("%.*s (%d) WARNING: %.*s\n",
derr.printf("%.*s (%d) %.*s: %.*s\n",
currentLocation.filename,
currentLocation.lineNo, msg
currentLocation.lineNo,
error ? "ERROR" : "WARNING",
msg
);
version (Windows) {
SetConsoleTextAttribute(h, csbi.wAttributes);
}
exitCode = 1;
}
@ -1163,7 +1196,12 @@ unittest {
assert(filenameExt("test\\foo.bar") == 8);
}
char[] makeEscape(char[] s) {
return replace(s, "$", "$$");
}
Stream openInputFile(char[] filename) {
makeSources ~= ' ' ~ makeEscape(filename);
try {
return new BufferedFile(filename, FileMode.In);
} catch (OpenException e) {
@ -1183,6 +1221,9 @@ Stream openOutputFile(char letter, char[] defaultExt) {
} else {
filename = optionParameters[letter - 'a'];
}
if (letter == 'o') {
makeTarget = makeEscape(filename);
}
try {
return new BufferedFile(filename, FileMode.OutNew);
} catch (OpenException e) {
@ -1716,7 +1757,7 @@ ubyte calculateBranch(int offset) {
if (offset < -0x80 || offset > 0x7f) {
int dist;
if (offset < 0) {
dist = 0x80 - offset;
dist = -offset - 0x80;
} else {
dist = offset - 0x7f;
}
@ -3043,9 +3084,12 @@ int main(char[][] args) {
char[] arg = args[i];
if (isOption(arg)) {
char letter = arg[1];
if (letter >= 'A' && letter <= 'Z')
letter += 'a' - 'A';
switch (letter) {
case 'c':
case 'i':
case 'm':
case 'p':
case 'q':
case 'u':
@ -3110,6 +3154,7 @@ int main(char[][] args) {
"/i Don't list included files\n"
"/l[:filename] Generate listing\n"
"/o:filename Set object file name\n"
"/M Print Makefile rule\n"
"/p " ~ OPTION_P_DESC ~ "\n"
"/q Suppress info messages\n"
"/t[:filename] List label table\n"
@ -3125,13 +3170,7 @@ int main(char[][] args) {
listLabelTable();
}
} catch (AssemblyError e) {
if (line !is null) {
derr.printf("%.*s\n", line);
}
derr.printf("%.*s (%d) ERROR: %.*s\n",
currentLocation.filename,
currentLocation.lineNo, e.msg
);
warning(e.msg, true);
exitCode = 2;
}
if (listingStream !is null) {
@ -3140,10 +3179,48 @@ int main(char[][] args) {
if (objectStream !is null) {
objectStream.close();
}
if (exitCode <= 1 && !getOption('q')) {
dout.printf("%d lines of source assembled\n", totalLines);
if (objectBytes > 0) {
dout.printf("%d bytes written to the object file\n", objectBytes);
if (exitCode <= 1) {
if (!getOption('q')) {
dout.printf("%d lines of source assembled\n", totalLines);
if (objectBytes > 0) {
dout.printf("%d bytes written to the object file\n", objectBytes);
}
}
if (getOption('m')) {
dout.printf("%.*s:%.*s\n\txasm", makeTarget, makeSources);
for (int i = 1; i < args.length; i++) {
char[] arg = args[i];
if (isOption(arg)) {
char letter = arg[1];
if (letter >= 'A' && letter <= 'Z')
letter += 'a' - 'A';
switch (letter) {
case 'm':
break;
case 'o':
if (arg[0] == '/') {
dout.printf(" /%c:$@", arg[1]);
} else {
dout.printf(" -%c $@", arg[1]);
++i;
}
break;
default:
if (arg[0] == '-'
&& (letter == 'd' || letter == 'l' || letter == 't')
&& i + 1 < args.length && !isOption(args[i + 1])) {
dout.printf(" %.*s %.*s", arg, makeEscape(args[++i]));
}
else {
dout.printf(" %.*s", makeEscape(arg));
}
break;
}
continue;
}
dout.printf(" $<");
}
dout.printf("\n");
}
}
return exitCode;

705
xasm.html
View File

@ -1,705 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>xasm 3.0.1</title>
<meta name="Author" content="Piotr Fusik"/>
</head>
<body>
<h2>NAME</h2>
<p>xasm - 6502 cross-assembler</p>
<h2>SYNOPSIS</h2>
<p><tt>xasm source [options]</tt></p>
<h2>DESCRIPTION</h2>
<p><b>xasm</b> is a cross-assembler which generates code for the 6502
processor.</p>
<p><tt>source</tt> is the name of the source file. If no filename extension
is given, <tt>.asx</tt> is appended. The default action (when invoked without
options) is to assembly <tt>source</tt>, writing the result to a file with
the <tt>.obx</tt> extension.</p>
<h2>OPTIONS</h2>
<dl>
<dt><tt>/c</tt></dt>
<dd>List lines skipped due to a false condition.</dd>
<dt><a id="new_deflabel"/><tt>/d:label=value</tt></dt>
<dd>Define a label.
<tt>label</tt> should be a valid label name.
<tt>value</tt> may be any expression (it may use forward references
to labels defined in the source file).
You may use several <tt>/d</tt> options to define many labels
from the command line.</dd>
<dt><tt>/i</tt></dt>
<dd>Do not list included files. Only main source file will be listed.</dd>
<dt><tt>/l[:filename]</tt></dt>
<dd>Generate a listing. If no <tt>filename</tt> is given, the listing is written
to <tt>source.lst</tt>, where <tt>source</tt> is the name of the source file
without the extension.</dd>
<dt><tt>/o:filename</tt></dt>
<dd>Set object file name. The default is <tt>source.obx</tt>.
You may use the null device (<tt>/o:nul</tt>) to generate no object file.</dd>
<dt><a id="new_fullpaths"/><tt>/p</tt></dt>
<dd>Print fully qualified file names in listing and error messages.
This option works only on Windows and is silently ignored on other platforms.</dd>
<dt><a id="new_quiet"/><tt>/q</tt></dt>
<dd>Suppress info messages.
Quiet mode. Prevents <b>xasm</b> from printing the logo and the summary.</dd>
<dt><tt>/t[:filename]</tt></dt>
<dd>List label table. If <tt>filename</tt> is omitted then the table is appended
to the listing.</dd>
<dt><a id="new_unlabels"/><tt>/u</tt></dt>
<dd>Issue a warning message for each label whose value is unused.</dd>
</dl>
<p>Alternatively, you may use Unix-style options, for example:</p>
<pre>xasm -i -d DEBUG=1 -l listing.lst source.asx
</pre>
<h2>SYNTAX</h2>
<p>Source files should be plain ASCII files. LF, CR, CR/LF and Atari line terminators
are supported. Labels and instructions are case-insensitive.</p>
<p><b>xasm</b> is backward compatible with Quick Assembler.
To compile QA sources with <b>xasm</b>, simply replace ATASCII-specific characters
with their integer codes. You also have to change all <tt>OPT</tt> directives,
but usually you can simply remove them.</p>
<p>A <i>label</i> is a symbol that represents a 32-bit signed integer.
You can define a label by putting its name at the beginning of a line
(with no spaces before). Unless you use the <tt>EQU</tt> directive,
the label is assigned the current value of the origin counter.</p>
<p>Instructions and directives must be preceded with some whitespace.
Note that in <b>xasm</b> you can use instruction and directive
names as label names. For example</p>
<pre>nop
</pre><p>defines a label called <tt>nop</tt>, whereas</p>
<pre> nop
</pre><p>is a 6502 instruction.</p>
<p>Full comment lines must start with a semicolon, a pipe or an asterisk,
with optional label definition and spaces before. Here are examples
of full comment lines:</p>
<pre>; this is a comment
* so it is
label | and this too
</pre>
<p><a id="new_linerep"/>Lines with instructions (and some directives)
may be <i>repeated</i>. A single line may be assembled several times,
for example:</p>
<pre>:4 asl @
table :32*5 dta 5
</pre>
<p>In lines with instructions or directives, a comment starts immediately
after the instruction/directive has been successfully parsed.
That is, <b>xasm</b> does not require a special character to start a comment.</p>
<pre> lda foo ; this is a comment
sta bar so it is
tax #0 tax has no operand, therefore #0 starts this comment
</pre>
<p><a id="new_pairing"/>You may put two instructions in one line
so they share the operand. For example:</p>
<pre> eor:sta foo
</pre>
<p>is equivalent to</p>
<pre> eor foo
sta foo
</pre>
<p>Note that</p>
<pre> lda:tax #0
</pre><p>is allowed because <tt>#0</tt> is treated as a comment for <tt>tax</tt>.</p>
<h2>EXPRESSIONS</h2>
<p>Expressions are numbers combined with operators and brackets.
You should use square brackets, because parentheses are reserved
for 6502 indirect addressing.</p>
<p>Numbers can be expressed as:</p>
<ul>
<li>a 32-bit decimal integer, e.g. <tt>-12345</tt></li>
<li>a 32-bit hexadecimal integer, e.g. <tt>$abcd</tt></li>
<li>a 32-bit binary integer, e.g. <tt>%10100101</tt></li>
<li>an ASCII character, e.g. <tt>'a'</tt> or <tt>"a"</tt></li>
<li>origin counter: <tt>*</tt></li>
<li>a hardware register, e.g. <tt>^4e</tt></li>
<li><a id="new_opcode"/>an op-code, e.g. <tt>{lda #0}</tt> equals
<tt>$a9</tt></li>
<li><a id="new_linecnt"/>the line repeat counter: <tt>#</tt></li>
</ul>
<p>Abbreviations of Atari hardware registers are provided to save you
the trouble of typing two extra characters (<tt>^4e</tt> vs <tt>$d40e</tt>)
and to ease 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.</p>
<table>
<tr><th>Syntax</th><th>Chip</th>
<th>Value in the Atari 8-bit<br/>computer mode (<tt>opt g-</tt>)</th>
<th>Value in the Atari 5200<br/>game console mode (<tt>opt g+</tt>)</th>
</tr>
<tr><td><tt>^0x</tt></td><td>GTIA</td>
<td><tt>$D00x</tt></td><td><tt>$C00x</tt></td></tr>
<tr><td><tt>^1x</tt></td><td>GTIA</td>
<td><tt>$D01x</tt></td><td><tt>$C01x</tt></td></tr>
<tr><td><tt>^2x</tt></td><td>POKEY</td>
<td><tt>$D20x</tt></td><td><tt>$E80x</tt></td></tr>
<tr><td><tt>^3x</tt></td><td>PIA</td>
<td><tt>$D30x</tt></td><td>error (there's no PIA chip)</td></tr>
<tr><td><tt>^4x</tt></td><td>ANTIC</td>
<td><tt>$D40x</tt></td><td><tt>$D40x</tt></td></tr>
</table>
<p>An op-code is the single-byte op-code of the instruction inside braces.
The operand of the instruction is discarded and is necessary 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.
<a id="new_op_op"/>You can skip the operand if the addressing mode
is fixed. Examples:
<tt>{lda #}</tt>, <tt>{jsr}</tt>, <tt>{bne}</tt>, <tt>{jmp ()}</tt>,
<tt>{sta a:,x}</tt>.</p>
<p>You can use the line repeat counter (<tt>#</tt>) in the repeated lines.
It counts the iterations starting from zero. Examples:</p>
<pre>: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
</pre>
<p>The follownig binary operators are supported:</p>
<ul>
<li><tt>+&nbsp;</tt> Addition</li>
<li><tt>-&nbsp;</tt> Subtraction</li>
<li><tt>*&nbsp;</tt> Multiplication</li>
<li><tt>/&nbsp;</tt> Division</li>
<li><tt>%&nbsp;</tt> Remainder</li>
<li><tt>&amp;&nbsp;</tt> Bitwise AND</li>
<li><tt>|&nbsp;</tt> Bitwise OR</li>
<li><tt>^&nbsp;</tt> Bitwise XOR</li>
<li><tt>&lt;&lt;</tt> Arithmetic shift left</li>
<li><tt>&gt;&gt;</tt> Arithmetic shift right</li>
<li><tt>=&nbsp;</tt> Equal</li>
<li><tt>==</tt> Equal (same as <tt>=</tt>)</li>
<li><tt>&lt;&gt;</tt> Not equal</li>
<li><tt>!=</tt> Not equal (same as <tt>&lt;&gt;</tt>)</li>
<li><tt>&lt;&nbsp;</tt> Less than</li>
<li><tt>&gt;&nbsp;</tt> Greater than</li>
<li><tt>&lt;=</tt> Less or equal</li>
<li><tt>&gt;=</tt> Greater or equal</li>
<li><tt>&amp;&amp;</tt> Logical AND</li>
<li><tt>||</tt> Logical OR</li>
</ul>
<p><a id="new_unary"/>The following unary operators are supported:</p>
<ul>
<li><tt>+&nbsp;</tt> Plus (does nothing)</li>
<li><tt>-&nbsp;</tt> Minus (changes the sign)</li>
<li><tt>~&nbsp;</tt> Bitwise NOT (complements all bits)</li>
<li><tt>!&nbsp;</tt> Logical NOT (changes true to false and vice versa)</li>
<li><tt>&lt;&nbsp;</tt> Low (extracts the low byte)</li>
<li><tt>&gt;&nbsp;</tt> High (extracts the high byte)</li>
</ul>
<p>The operator precedence is following:</p>
<table>
<tr><td>first</td><td><tt>[]</tt></td>
<td>(brackets)</td></tr>
<tr><td> </td><td><tt>+ - ~ &lt; &gt;</tt></td>
<td>(unary)</td></tr>
<tr><td> </td><td><tt>* / % &amp; &lt;&lt; &gt;&gt;</tt></td>
<td>(binary)</td></tr>
<tr><td> </td><td><tt>+ - | ^</tt></td>
<td>(binary)</td></tr>
<tr><td> </td><td><tt>= == &lt;&gt; != &lt; &gt; &lt;= &gt;=</tt></td>
<td>(binary)</td></tr>
<tr><td> </td><td><tt>!</tt></td>
<td>(unary)</td></tr>
<tr><td> </td><td><tt>&amp;&amp;</tt></td>
<td>(binary)</td></tr>
<tr><td>last </td><td><tt>||</tt></td>
<td>(binary)</td></tr>
</table>
<p>Note that although the operators are similar to those used in C, C++
and Java, their priorities are different than in these languages.</p>
<p>Compare and logical operators assume that zero is false and a non-zero
is true. They return 1 for true.</p>
<p>While calculating an expression, signed 32-bit arithmetic is used.
When range of 32 bits is exceeded, an '<tt>Arithmetic overflow</tt>' error
occurs.</p>
<h2>DIRECTIVES</h2>
<dl>
<dt><tt><b>EQU</b></tt> - assign a value of an expression to the label</dt>
<dd>Examples:
<pre>five equ 5
here equ *
</pre></dd>
<dt><a id="new_opt"/><tt><b>OPT</b></tt> - set assembly options</dt>
<dd>Five options are available:
<ul>
<li><tt>F</tt> - fill the space between <tt>ORG</tt>s
with <tt>$FF</tt></li>
<li><tt>G</tt> - Atari 5200 mode for hardware register abbreviations</li>
<li><tt>H</tt> - generate Atari executable headers</li>
<li><tt>L</tt> - write to the listing</li>
<li><tt>O</tt> - write to the object file</li>
</ul>
You can turn any of these on or off.<br/>
The default (if no <tt>OPT</tt> specified) is <tt>opt f-g-h+l+o+</tt>.<br/>
Examples:
<pre> opt l- listing off
opt l+o- listing on, object file off
opt f+g+h- useful for Atari 5200 cartridges - raw output format, 5200 hw regs
</pre></dd>
<dt><tt><b>ORG</b></tt> - change value of the origin counter</dt>
<dd>If Atari executable headers are enabled, you can use a prefix:
<ul>
<li><tt>a:</tt> starts a new block even if it is not necessary because
the new address equals the current address.</li>
<li><tt>f:</tt> is same as <tt>a:</tt>, but additionally generates
a <tt>$FF,$FF</tt> prefix before the new header. The prefix is automatically
generated at the beginning of the file.</li>
</ul>
Examples:
<pre> org $600
org f:$700
table org *+100
</pre>
In the latter example <tt>table</tt> points to 100 bytes
of uninitialized data (label is assigned to <tt>*</tt>
before the <tt>ORG</tt> directive is executed).
<p><a id="new_orgr"/>Starting with version 2.6.0, <b>xasm</b> supports code
that is relocated in the memory at runtime. Let's say you want your code
to be located on the zero page. You can't normally load it directly into this
place, so you load it at a different address and then move in your program.
<tt>org r:</tt> changes the address that it used for code generation
but not the address used for generating Atari executable headers.
Example:</p>
<pre> 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
</pre>
<p>Note that both <tt>*</tt> and label definitions use the counter used
for code generation. There is no direct access to the other counter,
because I think this is not useful. If you really need it, you can
always type something like:</p>
<pre>where_am_i equ *-code_zpage+code_loaded
</pre></dd>
<dt><a id="new_dta"/><tt><b>DTA</b></tt> - define data</dt>
<dd>
<ul>
<li>integers
<ul>
<li>bytes: <tt>b(200)</tt> or simply <tt>200</tt></li>
<li>words: <tt>a(10000)</tt></li>
<li>low bytes of words: <tt>l(511)</tt> defines byte 255</li>
<li>high bytes of words: <tt>h(511)</tt> defines byte 1</li>
</ul>
You may enter many expressions in parentheses and combine different types
of data in a single line, separating things with commas.<br/>
You may also define a sine lookup table. The syntax is:<br/>
<tt>sin(center,amp,size,first,last)</tt><br/>
where:
<ul>
<li><tt>center</tt> is a number which is added to every sine value</li>
<li><tt>amp</tt> is the sine amplitude</li>
<li><tt>size</tt> is the sine period</li>
<li><tt>first,last</tt> define the range of sine arguments.
They are optional. The default are <tt>0,size-1</tt>.</li>
</ul>
Example: <tt>dta a(sin(0,1000,256,0,63))</tt> defines a table of 64 words
representing a quarter of sine with the amplitude of 1000.</li>
<li>real numbers: <tt>r(-1.23456e12)</tt><br/>
Real numbers are stored in the 6-byte Atari Floating-Point format.</li>
<li>text strings
<ul>
<li>ASCII strings: <tt>c'Text'</tt> or <tt>c"Text"</tt></li>
<li>ANTIC strings: <tt>d'Text'</tt> or <tt>d"Text"</tt></li>
</ul>
A character string consists of any of characters surrounded by quotation
marks. You can include the quotation marks in the string by doubling them.<br/>
Placing a <tt>*</tt> character after a string inverts
the highest bit in every byte of the string.</li>
</ul>
Examples of <tt>DTA</tt>:
<pre>
dta b(1,2),3,a(1000,-1),l(12345,sin(0,127,256))
dta d"ANTIC"*,c'It''s a string',$9b
</pre></dd>
<dt><tt><b>ICL</b></tt> - include another source file</dt>
<dd>Specifies another file to be included in the assembly as if the contents
of the referenced file appeared in place of the <tt>ICL</tt> statement.
The included file may contain other <tt>ICL</tt> statements.
The <tt>.asx</tt> extension is added if none given.<br/>
Examples:
<pre>
icl 'macros.asx'
icl 'lib/fileio'
</pre>
Note: for portability, you should use only relative paths and slash
as the separator. This assures that your sources will compile under Windows
and Linux.</dd>
<dt><tt><b>END</b></tt> - end assembling file</dt>
<dd>Remaining part of the file is not assembled. If this statement does
not occur, the assembler stops assembling when it encounters the end
of the file.<br/>
Example:
<pre>
end
</pre></dd>
<dt><tt><b>INS</b></tt> - insert contents of file</dt>
<dd>Copies every byte of the specified file into the object file and updates
the origin counter, as if these bytes were defined with <tt>DTA</tt>.<br/>
You may specify a range of the file to insert. The syntax is:
<pre>
ins 'file'[,offset[,length]]
</pre>
The first byte in a file has the offset of zero.<br/>
If the offset is negative, it counts from the end of the file.<br/>
Examples:
<pre>
ins 'picture.raw'
ins 'file',-256 insert last 256 bytes of file
ins 'file',10,10 insert bytes 10..19 of file
</pre></dd>
<dt><tt><b>RUN</b></tt> - set run address in the Atari executable format</dt>
<dd><pre> run addr
</pre>
is equivalent to:
<pre> org $2e0
dta a(addr)
</pre>
Example:
<pre> run main
</pre></dd>
<dt><tt><b>INI</b></tt> - set init address in the Atari executable format</dt>
<dd>Example:
<pre> ini showpic
</pre></dd>
<dt><tt><b>ERT</b></tt> - generate error if expression evaluates to true</dt>
<dd>Examples:
<pre> ert *&gt;$c000
ert len1&gt;$ff||len2&gt;$ff
</pre></dd>
<dt><a id="new_eli"/><tt><b>IFT</b></tt> - assemble if expression is
true<br/>
<tt><b>ELI</b></tt> - else if<br/>
<tt><b>ELS</b></tt> - else<br/>
<tt><b>EIF</b></tt> - end if</dt>
<dd>With these directives you can construct fragments which
are assembled when a condition is met.
Conditional constructions can be nested.<br/>
Example:
<pre>noscr equ 1
widescr equ 1
ift noscr
lda #0
eli widescr
lda #$23
els
lda #$22
eif
sta $22f
</pre>
The above example can be rewritten using the line repeating feature:
<pre>noscr equ 1
widescr equ 1
:noscr lda #0
:!noscr&amp;&amp;widescr lda #$23
:!noscr&amp;&amp;!widescr lda #$22
sta $22f
</pre></dd>
</dl>
<h2>PSEUDO-COMMANDS</h2>
<p>Pseudo-commands are built-in macros.</p>
<dl>
<dt><tt><b>ADD</b></tt> - addition without carry</dt>
<dd>If you have ever programmed a 6502, you must have noticed that you had
to use a <tt>CLC</tt> before <tt>ADC</tt> for every simple addition.<br/>
<b>xasm</b> can do it for you. <tt>ADD</tt> replaces two instructions:
<tt>CLC</tt> and <tt>ADC</tt>.</dd>
<dt><tt><b>SUB</b></tt> - subtraction</dt>
<dd>It is <tt>SEC</tt> and <tt>SBC</tt>.</dd>
<dt><a id="new_repskip"/><tt><b>RCC, RCS, REQ, RMI, RNE, RPL, RVC,
RVS</b></tt> - conditional repeat</dt>
<dd>These are branches to the previous instruction.
They take no operand, because the branch target
is the address of the previously assembled instruction.<br/>
Example:
<pre> ldx #0
mva:rne $500,x $600,x+
</pre>
The example code copies memory $500-$5ff to $600-$6ff.
Here is the same written with standard 6502 commands only:
<pre> ldx #0
loop lda $500,x
sta $600,x
inx
bne loop
</pre></dd>
<dt><tt><b>SCC, SCS, SEQ, SMI, SNE, SPL, SVC, SVS</b></tt> - conditional
skip</dt>
<dd>These are branches over the next instructions. No operand is required,
because the target is the address of the instruction following
the next instruction.<br/>
Example:
<pre> lda #40
add:sta $80
scc:inc $81
</pre>
In the above example the word-sized variable $80 is incremented by 40.</dd>
<dt><tt><b>JCC, JCS, JEQ, JMI, JNE, JPL, JVC, JVS</b></tt> - conditional
jumps</dt>
<dd>These are a kind of 'long' branches. While standard branches
(such as <tt>BNE</tt>) have range of -128..+127, these jumps have range
of 64 kB.<br/>
Example:
<pre> jne dest
</pre>is equivalent to:
<pre> seq:jmp dest
</pre></dd>
<dt><tt><b>INW</b></tt> - increment word</dt>
<dd>Increments a 16-bit word in the memory.<br/>
Example:
<pre> inw dest
</pre>is equivalent to:
<pre> inc dest
sne:inc dest+1
</pre></dd>
<dt><tt><b>MVA, MVX, MVY</b></tt> - move byte using accumulator, X or Y</dt>
<dd>Each of these pseudo-commands requires two operands
and substitutes two commands:
<pre> mva source dest = lda source : sta dest
mvx source dest = ldx source : stx dest
mvy source dest = ldy source : sty dest
</pre></dd>
<dt><a id="new_mwinde"/><tt><b>MWA, MWX, MWY</b></tt> - move word using
accumulator, X or Y</dt>
<dd>These pseudo-commands require two operands
and are combinations of two <tt>MV*</tt>'s:
one to move the low byte, and the other to move the high byte.<br/>
You can't use indirect nor pseudo addressing mode with <tt>MW*</tt>.
Destination must be an absolute address, optionally indexed.<br/>
When source is also an absolute address, an <tt>mw* source dest</tt> expands to:
<pre> mv* source dest
mv* source+1 dest+1
</pre>
When source is an immediate value, an <tt>mw* #immed dest</tt> expands to:
<pre> mv* &lt;immed dest
mv* &gt;immed dest+1
</pre>
When <tt>&lt;immed</tt> equals <tt>&gt;immed</tt> and <tt>immed</tt>
is not forward-referenced, <b>xasm</b> skips the second <tt>LD*</tt>:
<pre> mv* &lt;immed dest
st* dest+1
</pre>
If possible, <tt>MWX</tt> and <tt>MWY</tt> use increment/decrement
commands. For example, <tt>mwx #1 dest</tt> expands to:
<pre> ldx #1
stx dest
dex
stx dest+1
</pre></dd>
</dl>
<h2>ADDRESSING MODES</h2>
<p>All addressing modes are entered in the standard 6502 convention except for
the accumulator addressing mode, which should be marked with
the <tt>@</tt> character (as in Quick Assembler).</p>
<p>There are two extra immediate addressing modes:
<tt>&lt;</tt> and <tt>&gt;</tt>,
which use the low/high byte of a 16-bit word constant.
They are for Quick Assembler compatibility.
You can use traditional <tt>#&lt;</tt> and <tt>#&gt;</tt>.
Note that <tt>lda &gt;$ff+5</tt> loads 1 (<tt>&gt;$104</tt>),
while <tt>lda #&gt;$ff+5</tt>
loads 5 (<tt>0+5</tt>) to the accumulator, because the unary operator
<tt>&gt;</tt> has a higher priority than the binary plus.</p>
<p>You can explicitly choose absolute (<tt>a:</tt>)
and zero-page (<tt>z:</tt>) addressing modes.</p>
<p>Examples:</p>
<pre>
nop
asl @
lda &gt;$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
</pre>
<p>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
<tt>MWA</tt>, <tt>MWX</tt> and <tt>MWY</tt>:</p>
<pre> 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
<a id="new_adrmodes"/> cmd (z),0+ = ldy #0 : cmd (z),y : iny
cmd (z),0- = ldy #0 : cmd (z),y : dey
</pre>
<h2>HISTORY</h2>
<h3>Version 3.0.1 (2007-04-22)</h3>
<ul>
<li>fixed a bug in <tt>OPT H-</tt> mode</li>
<li>made <b>xasm</b> compilable with the latest D compiler v1.010
(there were incompatible changes in the D language and library)</li>
</ul>
<h3>Version 3.0.0 (2005-05-22)</h3>
<ul>
<li>rewritten from the x86 assembly language to the
<a href="http://www.digitalmars.com/d">D programming language</a>
- Linux version is now available and plain DOS is no longer supported</li>
<li>no limits for the line length, number of <tt>ICL</tt>s, <tt>ORG</tt>s,
<tt>IFT</tt>s and labels</li>
<li>Unix-style command-line options are supported:
<pre>xasm -i -d DEBUG=1 -l listing.lst source.asx
</pre></li>
<li><tt>/e</tt> option is no longer supported</li>
<li>the label table is now sorted alphabetically</li>
</ul>
<h3>Version 2.6.1 (2005-05-21)</h3>
<ul>
<li>no more "Arithmetic overflow" and "Division by zero" errors when correctly
using forward-referenced labels (bug found by Marcin Lewandowski)</li>
<li>the following now assembles:
<pre> ift 0
foo equ 1
ift foo
eif
eif
</pre>
(bug found by Adrian Matoga)</li>
<li>errors for non-existing <tt>INC @</tt> and <tt>DEC @</tt></li>
<li>negative numbers fixed in the listing</li>
</ul>
<h3>Version 2.6.0 (2005-02-07)</h3>
<ul>
<li>long file names are supported under Windows</li>
<li><a href="#new_orgr">support for code that is relocated at runtime</a></li>
<li><a href="#new_linecnt">line repeat counter</a></li>
<li>label values are now 32-bit, not just 17-bit</li>
<li>command-line options <tt>/n</tt> and <tt>/s</tt> are no longer
supported</li>
<li>fatal I/O errors (such as floppy not ready) no longer print the annoying
'<tt>Abort, Retry, Ignore</tt>' message</li>
</ul>
<h3>Version 2.5.2 (2002-10-03)</h3>
<ul>
<li>version 2.5.1 broke Unix EOLs - fixed</li>
<li>version 2.5.1 omitted all blank/comment/label lines, unless <tt>/c</tt>
was used</li>
</ul>
<h3>Version 2.5.1 (2002-08-21)</h3>
<ul>
<li>fixed assembling sources with Atari EOLs</li>
<li>blank/comment/label lines in false conditionals are now correctly omitted
in listing</li>
</ul>
<h3>Version 2.5 (2002-07-08)</h3>
<ul>
<li>fixed another bug, very similar to the previous one, e.g.
<pre> ift 0
:label nop
eif
</pre>
reported <tt>Label not defined before</tt> error for the repeat count</li>
<li><a href="#new_opt"><tt>OPT F+</tt> causes <tt>ORG</tt>s to fill the space
between the old and the new location with <tt>$FF</tt>s</a></li>
<li><a href="#new_opt"><tt>OPT G+</tt> enables Atari 5200 mode for hardware
register abbreviations</a></li>
</ul>
<h3>Version 2.4.1 (2002-06-27)</h3>
<ul>
<li>fixed a bug related to label definitions in conditionally skipped code,
e.g.
<pre> ift 0
label
eif
</pre>
reported <tt>No ORG specified</tt> error for the label definition</li>
</ul>
<h3>Version 2.4 (2002-05-22)</h3>
<ul>
<li>fixed a bug causing incorrect unary operator precedence</li>
<li>fixed wrong label value after a skip pseudo-command</li>
<li>the assembler is .EXE (.COM caused problems with DJGPP make due
to a bug in the DJGPP runtime)</li>
<li>the assembler is not compressed (so it occupies less space in the ZIP)</li>
<li>improved command-line parsing: options may be used before source file
name, tab character is a valid separator, <tt>/</tt> may be used as a directory
separator</li>
<li>error and warning messages are written to stderr, not stdout</li>
<li>added <tt>==</tt> (equals) operator, which is equivalent to
<tt>=</tt>(but is more natural for C/C++/Java programmers)</li>
<li><a href="#new_deflabel">added <tt>/d:label=value</tt> option: define
a label</a></li>
<li><a href="#new_fullpaths">added <tt>/p</tt> option: print full paths
in listing and error messages</a></li>
<li><a href="#new_quiet">added <tt>/q</tt> option: quiet mode</a></li>
<li><a href="#new_unlabels">added <tt>/u</tt> option: warn of unused
labels</a></li>
<li><a href="#new_opt">writing to the object file may be suppressed
with <tt>OPT O-</tt></a></li>
<li><a href="#new_eli">added <tt>ELI</tt> (else if) directive</a></li>
<li><a href="#new_mwinde"><tt>MWX</tt> and <tt>MWY</tt> may use
<tt>INX</tt>/<tt>DEX</tt> and <tt>INY</tt>/<tt>DEY</tt>, respectively,
for generating smaller code</a></li>
</ul>
<h3>Version 2.3 (2002-02-10)</h3>
<ul>
<li>double skip (e.g. <tt>SCC:SNE</tt>) bug fixed</li>
<li>real number two-digit exponent bug fixed</li>
<li>trailing spaces in a listing line are now truncated</li>
<li>label definitions allowed in blank, comment and repeated lines</li>
<li><a href="#new_unary">unary operators</a></li>
<li><a href="#new_dta"><tt>DTA</tt> implied byte mode</a></li>
<li><a href="#new_op_op">operand can be skipped for some op-codes</a></li>
</ul>
<h3>Version 2.2 (1999-09-10)</h3>
<ul>
<li>invalid absolute <tt>CPX</tt> and <tt>CPY</tt> op-codes fixed</li>
<li>fixed: addressing mode not checked for branch commands</li>
<li><tt>ICL</tt> in last line bug fixed</li>
<li><tt>OPT H-H+</tt> bug fixed</li>
<li>first <tt>ORG *</tt> bug fixed</li>
<li>origin setting not required until it is used</li>
<li>Unix ($0a), Macintosh ($0d) and Atari ($9b) EOLs allowed in the source</li>
<li>value of 'true' changed to 1</li>
<li>setting environment variables on error option</li>
<li>assembling only if source newer than object option</li>
<li><a href="#new_opcode">op-code extracting</a></li>
<li><a href="#new_linerep">line repeating</a></li>
<li><a href="#new_pairing">instructions pairing</a></li>
<li><a href="#new_repskip">conditional repeat and skip pseudo commands</a></li>
<li><a href="#new_adrmodes"><tt>(),0+</tt> and <tt>(),0-</tt> pseudo
addressing modes</a></li>
</ul>
<h3>Version 2.0 (1998-11-12)</h3>
<ul>
<li>truncating name of object bug fixed</li>
<li><tt>EQU</tt> and <tt>DTA</tt> forward reference bugs fixed</li>
<li>hex number recognizing bug fixed</li>
<li>now <tt>.OBX</tt> is the default extension for Atari executables</li>
<li>assembling options (switches and <tt>OPT</tt> directive)</li>
<li>listing generation</li>
<li>label table generation</li>
<li>conditional assembly</li>
<li>user errors</li>
<li>warnings</li>
<li>improved headers generation</li>
<li>improved expressions - 19 operators and brackets, 32-bit arithmetic</li>
<li>improved signed numbers</li>
<li>6 new pseudo commands (memory-to-memory move)</li>
<li>8 pseudo addressing modes</li>
<li>indirect conditional jumps</li>
<li>Atari floating-point numbers generation</li>
<li>improved <tt>INS</tt>: inserting specified part of file</li>
</ul>
<h3>Version 1.2 (1998-08-14)</h3>
<ul>
<li>first release</li>
</ul>
<h2>AUTHOR</h2>
<p>Piotr Fusik (<a href="mailto:fox@scene.pl">fox@scene.pl</a>)</p>
<h2>SEE ALSO</h2>
<p>xasm home page
(<a href="http://xasm.atari.org">http://xasm.atari.org</a>)</p>
</body>
</html>