mirror of
https://github.com/pfusik/xasm.git
synced 2025-02-13 10:31:05 +00:00
Documentation converted to HTML.
This commit is contained in:
parent
1223276618
commit
98b08afee8
509
xasm.htm
Normal file
509
xasm.htm
Normal file
@ -0,0 +1,509 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>X-Assembler 2.0 Manual</TITLE>
|
||||
</HEAD>
|
||||
<BODY BACKGROUND="6502PROC.GIF">
|
||||
<CENTER>
|
||||
<H1>X-Assembler version 2.0</H1>
|
||||
coded by Fox/Taquart
|
||||
<HR>
|
||||
</CENTER>
|
||||
<H2>INTRODUCTION</H2>
|
||||
The X-Assembler is an assembler, which generates code for the 6502 processor.
|
||||
It is 99% compatible with Quick Assembler on 8-bit Atari.
|
||||
<BR>
|
||||
<H3>System requirements</H3>
|
||||
<UL>
|
||||
<LI> a PC compatible computer with 386 or better CPU
|
||||
<LI> a MS-DOS compatible OS
|
||||
<LI> a numeric coprocessor for generating sinus tables.
|
||||
Your CPU probably has a built-in coprocessor.
|
||||
</UL>
|
||||
<BR>
|
||||
<H3>Creating a source program</H3>
|
||||
Source file should be standard text file with IBM-style EOLs: CR/LF. You can
|
||||
use any text editor on PC to prepare your source code.
|
||||
Single line of source should not be longer than 256 characters.
|
||||
There is no limitation on the length of the file.
|
||||
Source may contain tabulators - there are treated as spaces.
|
||||
Assembler is NOT case-sensitive.
|
||||
<BR>
|
||||
<H3>Converting Quick Assembler files</H3>
|
||||
You must convert Atari text file into PC text file (EOL's from $9b to $0d/$0a),
|
||||
ATASCII 0-31 and 128-255 characters should be replaced with standard ASCII
|
||||
characters, using QAsm expressions.<BR>
|
||||
You also have to change all OPT directives, but usually you needn't them
|
||||
at all.
|
||||
<BR>
|
||||
<H3>Assembling a source program</H3>
|
||||
Syntax (parameters in brackets are optional):<BR>
|
||||
<PRE>XASM source [options]
|
||||
</PRE><TT>'source'</TT> is name of source file.
|
||||
If no extension given, the .ASX is added by default.<P>
|
||||
Options are:
|
||||
<DL>
|
||||
<DT><TT>/c</TT>
|
||||
<DD>Enable listing false conditionals.
|
||||
<DT><TT>/i</TT>
|
||||
<DD>Disable listing included source.
|
||||
<DT><TT>/l[:fname]</TT>
|
||||
<DD>Enable generating listing. If no <TT>fname</TT> given, listing is written to source.lst.
|
||||
<DT><TT>/o:fname</TT>
|
||||
<DD>Specify object name. Default is <TT>source.obx</TT>.
|
||||
<DT><TT>/s</TT>
|
||||
<DD>Disable converting spaces to tabs. Using tabs makes listing file shorter.<BR>
|
||||
Tab stops are assumed to be every 8 characters.
|
||||
<DT><TT>/t[:fname]</TT>
|
||||
<DD>List label table. If no fname given, table is written at the end of listing.
|
||||
</DL>
|
||||
|
||||
If source is incorrect, X-Asm displays ONLY FIRST encountered error.<P>
|
||||
|
||||
Errorlevels returned by X-Asm:<BR>
|
||||
3 = bad parameters, assembling not started<BR>
|
||||
2 = error occured<BR>
|
||||
1 = warning(s) only<BR>
|
||||
0 = no errors, no warnings<BR>
|
||||
|
||||
<H3>Listing structure</H3>
|
||||
Line of listing includes:
|
||||
<UL>
|
||||
<LI> decimal number of line of source file (if source is different than in
|
||||
previous listed line, appropriate message line is generated)
|
||||
<LI> hexadecimal origin
|
||||
<LI> hexadecimal bytes written to object file
|
||||
Listed are also generated headers. A <TT>xxxx-yyyy></TT> in place of origin is
|
||||
a generated header: <TT>$xxxx</TT> is the first and <TT>$yyyy</TT> is the last byte of block.
|
||||
A <TT>FFFF></TT> represents two $ff bytes written as a header prefix.<P>
|
||||
A plus sign placed after hex numbers stands for more bytes written to object
|
||||
in this line, not listed through lack of space.
|
||||
<LI> remaining part of listing line is a copy of source
|
||||
</UL>
|
||||
|
||||
<H3>Label table structure</H3>
|
||||
Line of label table includes:
|
||||
<UL>
|
||||
<LI> some info of label:<BR>
|
||||
<TT>n</TT> - label not used<BR>
|
||||
<TT>2</TT> - label value known in pass 2 only (label definition uses forward reference
|
||||
and thus you can't do forward references to that label)
|
||||
<LI> hex value of label
|
||||
<LI> name of label
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<H2>X-ASM LANGUAGE STRUCTURE</H2>
|
||||
Lines of source code may be:
|
||||
<UL>
|
||||
<LI> empty lines - ignored, of course
|
||||
<LI> comments - ignored, too
|
||||
<LI> statements - not ignored :-)
|
||||
</UL>
|
||||
Comment lines must have one of the following characters in the FIRST column
|
||||
of the line: <TT>* ; |</TT>
|
||||
|
||||
<H3>Numbers</H3>
|
||||
Numbers are 32-bit signed integers, in the range of -$7fffffff..$7fffffff.
|
||||
A number can be:
|
||||
<UL>
|
||||
<LI> a decimal number <TT>-12345</TT>
|
||||
<LI> a hexadedecimal number <TT>$abcd</TT>
|
||||
<LI> a binary number <TT>%10100101</TT>
|
||||
<LI> a character <TT>'a'</TT> or <TT>"a"</TT> (new in 2.0!)
|
||||
<LI> a hardware register <TT>^31</TT>
|
||||
<LI> an origin counter <TT>*</TT>
|
||||
</UL>
|
||||
I think only 'a hardware register' should be explained. It is a short way
|
||||
of accessing Atari hardware registers:<P>
|
||||
<TT>^0x</TT> means <TT>$d00x</TT><BR>
|
||||
<TT>^1x</TT> means <TT>$d01x</TT><BR>
|
||||
<TT>^2x</TT> means <TT>$d20x</TT><BR>
|
||||
<TT>^3x</TT> means <TT>$d30x</TT><BR>
|
||||
<TT>^4x</TT> means <TT>$d40x</TT><BR>
|
||||
where x is a hexadecimal digit.
|
||||
|
||||
<H3>Expressions</H3>
|
||||
Expressions are numbers combined with operators and brackets.
|
||||
You should use square brackets, because parentheses are reserved
|
||||
for 6502 indirect addressing. Currently there are 19 operators:<P>
|
||||
|
||||
<TT>+ </TT>Addition<BR>
|
||||
<TT>- </TT>Subtraction<BR>
|
||||
<TT>* </TT>Multiplication<BR>
|
||||
<TT>/ </TT>Division<BR>
|
||||
<TT>% </TT>Remainder<BR>
|
||||
<TT>& </TT>Bitwise and<BR>
|
||||
<TT>| </TT>Bitwise or<BR>
|
||||
<TT>^ </TT>Bitwise xor<BR>
|
||||
<TT><< </TT>Arithmetic shift left<BR>
|
||||
<TT>>> </TT>Arithmetic shift right<BR>
|
||||
<TT>= </TT>Equal<BR>
|
||||
<TT><> </TT>Not equal<BR>
|
||||
<TT>!= </TT>Not equal (same as <>)<BR>
|
||||
<TT>< </TT>Less than<BR>
|
||||
<TT>> </TT>Greater than<BR>
|
||||
<TT><= </TT>Less or equal<BR>
|
||||
<TT>>= </TT>Greater or equal<BR>
|
||||
<TT>&& </TT>Logical and<BR>
|
||||
<TT>|| </TT>Logical or<P>
|
||||
|
||||
Operator precedence:
|
||||
<PRE>
|
||||
first []
|
||||
* / % & << >>
|
||||
+ - | ^
|
||||
= <> != < > <= >=
|
||||
&&
|
||||
last ||
|
||||
</PRE>
|
||||
Compare and logical operators assume that zero is false and non-zero is true.
|
||||
They return -1 for true.<P>
|
||||
When calculating expression, 32-bit arithmetic is used. When range of 32 bits
|
||||
is exceeded, <TT>'Arithmetic overflow'</TT> error is generated.<P>
|
||||
If result of expression has improper size, <TT>'Value out of range'</TT> error occurs.<P>
|
||||
Note difference beetwen X-Asm 2.0 and QAsm/X-Asm 1.2: in older assemblers,
|
||||
which used 16-bit arithmetic, a <TT>LDA 0-1</TT> was correct (<TT>LDA $ffff</TT>), but X-Asm 2.0
|
||||
encounters an error: address can't be negative.<P>
|
||||
X-Asm recognizes now signed bytes: <TT>LDA #-1</TT> is OK.
|
||||
|
||||
<H3>Statements</H3>
|
||||
A statement is divided into fields: a label field, an operation field,
|
||||
one or two operand fields, and a comment field. There should be at least
|
||||
one space between every two fields and there can't be any space within a field
|
||||
excluding strings.
|
||||
|
||||
<H4>Label field</H4>
|
||||
This field is optional. It is required only by the <TT>EQU</TT> directive.
|
||||
Specyfying this field definies a label. Defined label represents an integer
|
||||
of range -$ffff..$ffff.<P>
|
||||
Name of label must begin in column 1 and can contain letters, digits
|
||||
and underscores (<TT>_</TT>). Digit can't be label's first character. Name of label
|
||||
can be as long as you want and all the characters are meaningful.<P>
|
||||
In Quick Assembler only 6 leading characters were recognized
|
||||
and some programs may not compile well under X-Asm for this reason.<P>
|
||||
Defining a label without using <TT>EQU</TT> makes it equal to current value
|
||||
of the origin counter. Label can't be redefined.
|
||||
|
||||
<H4>Operation field</H4>
|
||||
Operation field is the only field which is always required.
|
||||
You have to put one or more spaces or tab characters between label
|
||||
and operation field. If no label is defined, line must start with a blank
|
||||
character. Operation field is always 3 letters long. It can be:
|
||||
<OL TYPE=a>
|
||||
<LI><I> a 6502 processor command</I>
|
||||
<LI><I> a compiler directive</I>
|
||||
<LI><I> a pseudo-command</I>
|
||||
</OL>
|
||||
<OL TYPE=a>
|
||||
<LI><I> 6502 command</I><BR>
|
||||
One of 56 well known processor commands.<BR><BR>
|
||||
|
||||
<LI><I> compiler directive</I><BR>
|
||||
One of the following:
|
||||
<DL>
|
||||
<DT><TT><B>EQU</B></TT> - assign a value of expression to the label
|
||||
<DD>Note that label represents a number, not a text macro.<P>
|
||||
Examples:
|
||||
<PRE>five equ 5
|
||||
ten equ five+five
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>OPT</B></TT> - set assembling options
|
||||
<DD>Currently there are two options: listing generating and headers generating.
|
||||
You can turn any of these on or off.<P>
|
||||
Examples:
|
||||
<PRE> opt l- listing off
|
||||
opt h- headers off
|
||||
opt l+h- listing on, headers off
|
||||
</PRE>
|
||||
Remember not to put a space between options:
|
||||
<PRE> opt l+ h-
|
||||
</PRE>
|
||||
is actually
|
||||
<PRE> opt l+
|
||||
</PRE>
|
||||
because h- is a comment.<P>
|
||||
Default (if no opt specified) is <TT>opt l+h+</TT>.<P>
|
||||
|
||||
<DT><TT><B>ORG</B></TT> - set new origin counter
|
||||
<DD>Examples:
|
||||
<PRE> org $600 code will be located starting from $0600
|
||||
table org *+100 'table' points to 100 bytes of uninitialized data
|
||||
</PRE>
|
||||
New! You can set some options applied to new header (if headers are on):
|
||||
<PRE> org $600
|
||||
rts
|
||||
org a:$601
|
||||
</PRE>
|
||||
'a:' tells X-Asm to always make a header, even it is unnecessary (as in above).
|
||||
So by default X-Asm 2.0 does not generate unnecessary headers, distinct from
|
||||
QAsm and X-Asm 1.2.
|
||||
<PRE> org f:$700
|
||||
</PRE>
|
||||
'f:' works same as 'a:', but additionally tells to generate a $ff,$ff prefix
|
||||
before header. X-Asm adds it to the first header in file by default, so use
|
||||
this option only if you want the $ff's somewhere inside.<P>
|
||||
|
||||
<DT><TT><B>DTA</B></TT> - define data
|
||||
<DD>You may define:
|
||||
<UL>
|
||||
<LI> numbers
|
||||
<UL>
|
||||
<LI> bytes: <TT>b(200)</TT>
|
||||
<LI> words: <TT>a(10000)</TT>
|
||||
<LI> low bytes of words: <TT>l(511)</TT> defines byte 255
|
||||
<LI> high bytes of words: <TT>h(511)</TT> defines byte 1
|
||||
You may enter many expressions in parentheses and combine different types
|
||||
of data in single line.<P>
|
||||
You may also define a sinus table. Enter this expression:<BR>
|
||||
<TT>sin(centre,amp,size,first,last)</TT><BR>
|
||||
where:
|
||||
<UL>
|
||||
<LI> centre is a number which is added to every value of sinus
|
||||
<LI> amp is the amplitude of sinus
|
||||
<LI> size is the period of sinus
|
||||
<LI> first,last define range of values in the table.
|
||||
They are optional. Default are 0,size-1.
|
||||
</UL>
|
||||
Example: <TT>dta a(sin(0,1000,256,0,63))</TT> defines table of 64 words representing
|
||||
a quarter of sinus with amplitude of 1000.
|
||||
<LI> real numbers: <TT>r(-1.23456e12)</TT><BR>
|
||||
Real numbers are written in 6-byte Atari Floating-Point format. You can't
|
||||
combine reals with operators, as you can integers.<P>
|
||||
</UL>
|
||||
<LI> text strings
|
||||
<UL>
|
||||
<LI> ASCII strings: <TT>c'Text'</TT> or <TT>c"Text"</TT>
|
||||
<LI> ANTIC strings: <TT>d'Text'</TT> or <TT>d"It's something new!"</TT>
|
||||
</UL>
|
||||
A character string consists of any of characters surrounded by quotation
|
||||
marks. Within a string, a single quotation mark character is
|
||||
represented by two succesive quotation marks.<P>
|
||||
Placing a '*' character after a string inverts bit 7 in every byte of string.<P>
|
||||
</UL>
|
||||
Examples of <TT>DTA</TT>:
|
||||
<PRE>
|
||||
dta b(2,5),a(1000,-1),l(12345,sin(0,127,256))
|
||||
dta d"ANTIC"*,c'It''s a string',b(155)
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>ICL</B></TT> - include another source file
|
||||
<DD>Specifies another file to be included in the assembly as if the contests of
|
||||
the referenced file appeared in place of the <TT>ICL</TT> statement. The included file
|
||||
may contain other <TT>ICL</TT> statements.<P>
|
||||
Examples:
|
||||
<PRE>
|
||||
icl 'macros.asx'
|
||||
icl 'c:\atari\xasm\fileio.asx'
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>END</B></TT> - end assembling of file
|
||||
<DD>Remaining part of the file is not assembled. If this statement does not occur,
|
||||
assembler stops assembling when encounters end of file.<BR>
|
||||
Example:
|
||||
<PRE>
|
||||
end
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>INS</B></TT> - insert contents of file
|
||||
<DD>Copies every byte of specified file into object file and moves origin counter,
|
||||
as if these bytes were defined with <TT>DTA</TT>.<P>
|
||||
Examples:
|
||||
<PRE>
|
||||
ins 'picture.raw'
|
||||
ins 'tables.dat'
|
||||
</PRE>
|
||||
New! You may specify range of inserted file. Syntax is:
|
||||
<PRE>
|
||||
ins 'file'[,offset[,length]]
|
||||
</PRE>
|
||||
First byte in file has offset 0.<P>
|
||||
If offset is negative, it is counted from the end of file.
|
||||
<PRE>
|
||||
ins 'file',-256 inserts last 256 bytes of file
|
||||
ins 'file',10,10 inserts bytes 10..19 of file
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>RUN</B></TT> - generate run address
|
||||
<DD>The Atari executable program should have run address specified. Remember that
|
||||
a program may be loaded in many areas of memory and started from any address.
|
||||
<PRE> run addr
|
||||
</PRE>
|
||||
is equivalent to:
|
||||
<PRE> org $2e0
|
||||
dta a(addr)
|
||||
</PRE>
|
||||
Examples:
|
||||
<PRE> run start
|
||||
run program
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>INI</B></TT> - generate init address
|
||||
<DD>The Atari executable program may have some routines which are executed during
|
||||
loading process. There may be many init blocks in one file.
|
||||
Examples:
|
||||
<PRE> ini init
|
||||
ini showpic
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>ERT</B></TT> - generate error if expression is true
|
||||
<DD>Examples:
|
||||
<PRE> ert *>$c000
|
||||
ert len1>$ff||len2>$ff
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>IFT</B></TT> - assemble if expression is true<BR>
|
||||
<TT><B>ELS</B></TT> - else<BR>
|
||||
<TT><B>EIF</B></TT> - end if<BR>
|
||||
<DD>Example:
|
||||
<PRE>noscr equ 1
|
||||
ift noscr
|
||||
lda #0
|
||||
els
|
||||
lda #$22
|
||||
eif
|
||||
sta $22f
|
||||
</PRE>
|
||||
|
||||
</DL>
|
||||
<LI><I> pseudo-command</I><BR>
|
||||
It is something like built-in macro. It replaces two or more standard
|
||||
processor commands. Note that it is not an illegal instruction and works
|
||||
on typical 6502.
|
||||
<DL>
|
||||
<DT><TT><B>ADD</B></TT> - addition without carry
|
||||
<DD>If you ever programmed 6502, you must have noticed that you had to use a <TT>CLC</TT>
|
||||
before <TT>ADC</TT> for every simple addition.<BR>
|
||||
X-Asm can do it for you. <TT>ADD</TT> simply replaces two instructions: <TT>CLC</TT> and <TT>ADC</TT>.<P>
|
||||
|
||||
<DT><TT><B>SUB</B></TT> - subtraction
|
||||
<DD>It is <TT>SEC</TT> and <TT>SBC</TT>.<P>
|
||||
|
||||
<DT><TT><B>JNE, JEQ, JCC, JCS, JPL, JMI, JVC, JVS</B></TT> - conditional jumps
|
||||
<DD>They are a kind of 'long' branches. While standard branches (<TT>BNE, BEQ</TT>) have
|
||||
range of -128..+127, these jumps have range of all 64 kB.<P>
|
||||
For example: a <TT>JNE DEST</TT> is replaced with:
|
||||
<PRE> beq *+5
|
||||
jmp dest
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>INW</B></TT> - increment word
|
||||
<DD>It is a 16-bit memory increment command. An <TT>INW DEST</TT> will be replaced by:
|
||||
<PRE> inc dest
|
||||
bne _skip
|
||||
inc dest+1
|
||||
_skip equ *
|
||||
</PRE>
|
||||
The <TT>_skip</TT> label is not declared of course.<P>
|
||||
|
||||
<DT><TT><B>MVA, MVX, MVY</B></TT> - move byte using accumulator, X or Y
|
||||
<DD>These pseudo-commands require two operands.
|
||||
<PRE> mva source dest = lda source : sta dest
|
||||
mvx source dest = ldx source : stx dest
|
||||
mvy source dest = ldy source : sty dest
|
||||
</PRE>
|
||||
|
||||
<DT><TT><B>MWA, MWX, MWY</B></TT> - move word using accumulator, X or Y
|
||||
<DD>Also require two operands. They are something like combination of two <TT>MV*</TT>'s:
|
||||
one to move low byte, and the other to move high byte.<P>
|
||||
You can't use indirect nor pseudo addressing modes with <TT>MW*</TT>.<P>
|
||||
Destination must be absolute address (indexed or not).<P>
|
||||
When source is also absolute, a <TT>MW* SOURCE DEST</TT> will be:
|
||||
<PRE> mv* source dest
|
||||
mv* source+1 dest+1
|
||||
</PRE>
|
||||
When source is immediate, a <TT>MW* #IMMED</TT> dest will be
|
||||
<PRE> mv* <immed dest
|
||||
mv* >immed dest+1
|
||||
</PRE>
|
||||
but when <IMMED = >IMMED and IMMED is not forward-referenced,
|
||||
X-Asm uses optimization:
|
||||
<PRE> mv* <immed dest
|
||||
st* dest+1
|
||||
</PRE>
|
||||
</DL>
|
||||
</OL>
|
||||
|
||||
<H4>Operand</H4>
|
||||
It depends on the operation field. Some statements don't need an operand
|
||||
or need two operands.<P>
|
||||
|
||||
6502 commands require operand depending on the addressing mode.
|
||||
Addressing modes should be entered in standard convention except
|
||||
the accumulator addressing mode, which should be marked with a <TT>@</TT> character
|
||||
(as in Quick Assembler).<P>
|
||||
|
||||
There are two extra immediate addressing modes: < and >, which use low/high
|
||||
byte of word is used rather than byte value.<P>
|
||||
|
||||
In absolute addressing modes, X-Asm examines expression and uses zero-page
|
||||
addressing mode if it thinks it is possible to do it. You may override it
|
||||
with <TT>a:</TT> and <TT>z:</TT> prefixes.<P>
|
||||
|
||||
Examples:
|
||||
<PRE>
|
||||
nop
|
||||
asl @
|
||||
lda >$1234 assembles to lda #$12
|
||||
lda $100,x
|
||||
lda a:0 generates 16-bit address
|
||||
jmp ($0a)
|
||||
lda ($80),y
|
||||
</PRE>
|
||||
|
||||
New! X-Asm 2.0 brings pseudo addressing modes. They are similar to
|
||||
pseudo-commands and you may use them as standard addressing modes
|
||||
in all 6502 commands and pseudo-commands, excluding <TT>MW*</TT>:
|
||||
<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
|
||||
</PRE>
|
||||
<H3>Problems</H3>
|
||||
These notes may help you solve problems:
|
||||
<UL>
|
||||
<LI> No spaces are allowed within a field.
|
||||
<PRE>label equ 1 + 2
|
||||
</PRE>
|
||||
causes label to be equal 1 (<TT>+ 2</TT> is treated as a comment).<P>
|
||||
|
||||
<LI> <TT><</TT> and <TT>></TT> represent addressing modes rather than LOW and HIGH operators.<P>
|
||||
You specify <TT>lda <table</TT>, not <TT>lda #<table</TT> like in most 6502 assemblers.<P>
|
||||
|
||||
<LI> Label definition does not include a colon
|
||||
<PRE>label: lda ^4b ERROR - colon after label name
|
||||
</PRE>
|
||||
|
||||
<LI> Exactly one run address should be specified<P>
|
||||
Remember that unlike in other assemblers
|
||||
<PRE> end start
|
||||
</PRE>
|
||||
does not tell the assembler that <TT>start</TT> is the run address (it is a comment).
|
||||
You must specify the run address with <TT>RUN</TT> directive.<P>
|
||||
|
||||
<LI> X-Asm reads source twice (in pass 1 and pass 2)<BR>
|
||||
This allows forward references, but not too complex.<P>
|
||||
Keep in mind that assembler should know all the values in second pass.<P>
|
||||
Example:
|
||||
<PRE>two equ one+one This value is known in 2nd pass only
|
||||
one equ 1 This value is known as early as in 1st pass
|
||||
</PRE>
|
||||
These values can be fixed in 2 passes.<P>
|
||||
But if you insert following statement as first line:
|
||||
<PRE>three equ one+two
|
||||
</PRE>
|
||||
X-Asm will generate an error because it doesn't know the value of <TT>three</TT> in
|
||||
second pass.<BR>
|
||||
(sorry for v1.2 users: <TT>EQU</TT> forward reference didn't work at all).<P>
|
||||
|
||||
<LI> X-Asm displays only first error<BR>
|
||||
When you correct one error don't be surpised if you get another one.<P>
|
||||
|
||||
<LI> If you encounter X-Asm works improperly, please <A HREF=mailto:pfusik@elka.pw.edu.pl>let me know</A>.
|
||||
</UL>
|
||||
</BODY>
|
||||
</HTML>
|
452
xasm.txt
452
xasm.txt
@ -1,452 +0,0 @@
|
||||
X-Assembler version 2.0
|
||||
=======================
|
||||
coded by Fox/Taquart
|
||||
|
||||
INTRODUCTION
|
||||
============
|
||||
The X-Assembler is an assembler, which generates code for the 6502 processor.
|
||||
It is 99% compatible with Quick Assembler on 8-bit Atari.
|
||||
|
||||
System requirements
|
||||
-------------------
|
||||
- a PC compatible computer with 386 or better CPU
|
||||
- a MS-DOS compatible OS
|
||||
- a numeric coprocessor for generating sinus tables
|
||||
Your CPU probably has a built-in coprocessor.
|
||||
|
||||
Creating a source program
|
||||
-------------------------
|
||||
Source file should be standard text file with IBM-style EOLs: CR/LF. You can
|
||||
use any text editor on PC to prepare your source code.
|
||||
Single line of source should not be longer than 256 characters.
|
||||
There is no limitation on the length of the file.
|
||||
Source may contain tabulators - there are treated as spaces.
|
||||
Assembler is NOT case-sensitive.
|
||||
|
||||
Converting Quick Assembler files
|
||||
--------------------------------
|
||||
You must convert Atari text file into PC text file (EOL's from $9b to $0d/$0a),
|
||||
ATASCII 0-31 and 128-255 characters should be replaced with standard ASCII
|
||||
characters, using QAsm expressions.
|
||||
You also have to change all OPT directives, but usually you needn't them
|
||||
at all.
|
||||
|
||||
Assembling a source program
|
||||
---------------------------
|
||||
Syntax (parameters in brackets are optional):
|
||||
XASM source [options]
|
||||
'source' is name of source file.
|
||||
If no extension given, the .ASX is added by default.
|
||||
Options are:
|
||||
/c
|
||||
Enable listing false conditionals.
|
||||
/i
|
||||
Disable listing included source.
|
||||
/l[:fname]
|
||||
Enable generating listing. If no fname given, listing is written to source.lst.
|
||||
/o:fname
|
||||
Specify object name. Default is source.obx.
|
||||
/s
|
||||
Disable converting spaces to tabs. Using tabs makes listing file shorter.
|
||||
Tab stops are assumed to be every 8 characters.
|
||||
/t[:fname]
|
||||
List label table. If no fname given, table is written at the end of listing.
|
||||
|
||||
If source is incorrect, X-Asm displays ONLY FIRST encountered error.
|
||||
|
||||
Errorlevels returned by X-Asm:
|
||||
3 = bad parameters, assembling not started
|
||||
2 = error occured
|
||||
1 = warning(s) only
|
||||
0 = no errors, no warnings
|
||||
|
||||
Listing structure
|
||||
-----------------
|
||||
Line of listing includes:
|
||||
- decimal number of line of source file (if source is different than in
|
||||
previous listed line, appropriate message line is generated)
|
||||
- hexadecimal origin
|
||||
- hexadecimal bytes written to object file
|
||||
Listed are also generated headers. A 'xxxx-yyyy>' in place of origin is
|
||||
a generated header: $xxxx is the first and $yyyy is the last byte of block.
|
||||
A 'FFFF>' represents two $ff bytes written as a header prefix.
|
||||
A plus sign placed after hex numbers stands for more bytes written to object
|
||||
in this line, not listed through lack of space.
|
||||
- remaining part of listing line is a copy of source
|
||||
|
||||
Label table structure
|
||||
---------------------
|
||||
Line of label table includes:
|
||||
- some info of label:
|
||||
n - label not used
|
||||
2 - label value known in pass 2 only (label definition uses forward reference
|
||||
and thus you can't do forward references to that label)
|
||||
- hex value of label
|
||||
- name of label
|
||||
|
||||
X-ASM LANGUAGE STRUCTURE
|
||||
========================
|
||||
Lines of source code may be:
|
||||
- empty lines - ignored, of course
|
||||
- comments - ignored, too
|
||||
- statements - not ignored :-)
|
||||
Comment lines must have one of the following characters in the FIRST column
|
||||
of the line: * ; |
|
||||
|
||||
Numbers
|
||||
-------
|
||||
Numbers are 32-bit signed integers, in the range of -$7fffffff..$7fffffff.
|
||||
A number can be:
|
||||
- a decimal number -12345
|
||||
- a hexadedecimal number $abcd
|
||||
- a binary number %10100101
|
||||
- a character 'a' or "a" (new in 2.0!)
|
||||
- a hardware register ^31
|
||||
- an origin counter *
|
||||
I think only 'a hardware register' should be explained. It is a short way
|
||||
of accessing Atari hardware registers:
|
||||
^0x means $d00x
|
||||
^1x means $d01x
|
||||
^2x means $d20x
|
||||
^3x means $d30x
|
||||
^4x means $d40x
|
||||
where x is a hexadecimal digit.
|
||||
|
||||
Expressions
|
||||
-----------
|
||||
Expressions are numbers combined with operators and brackets.
|
||||
You should use square brackets, because parentheses are reserved
|
||||
for 6502 indirect addressing. Currently there are 19 operators:
|
||||
|
||||
+ Addition
|
||||
- Subtraction
|
||||
* Multiplication
|
||||
/ Division
|
||||
% Remainder
|
||||
& Bitwise and
|
||||
| Bitwise or
|
||||
^ Bitwise xor
|
||||
<< Arithmetic shift left
|
||||
>> Arithmetic shift right
|
||||
= Equal
|
||||
<> Not equal
|
||||
!= Not equal (same as <>)
|
||||
< Less than
|
||||
> Greater than
|
||||
<= Less or equal
|
||||
>= Greater or equal
|
||||
&& Logical and
|
||||
|| Logical or
|
||||
|
||||
Operator precedence:
|
||||
first []
|
||||
* / % & << >>
|
||||
+ - | ^
|
||||
= <> != < > <= >=
|
||||
&&
|
||||
last ||
|
||||
|
||||
Compare and logical operators assume that zero is false and non-zero is true.
|
||||
They return -1 for true.
|
||||
When calculating expression, 32-bit arithmetic is used. When range of 32 bits
|
||||
is exceeded, 'Arithmetic overflow' error is generated.
|
||||
If result of expression has improper size, 'Value out of range' error occurs.
|
||||
Note difference beetwen X-Asm 2.0 and QAsm/X-Asm 1.2: in older assemblers,
|
||||
which used 16-bit arithmetic, a LDA 0-1 was correct (LDA $ffff), but X-Asm 2.0
|
||||
encounters an error: address can't be negative.
|
||||
X-Asm recognizes now signed bytes: LDA #-1 is OK.
|
||||
|
||||
Statements
|
||||
----------
|
||||
A statement is divided into fields: a label field, an operation field,
|
||||
one or two operand fields, and a comment field. There should be at least
|
||||
one space between every two fields and there can't be any space within a field
|
||||
excluding strings.
|
||||
|
||||
Label field
|
||||
~~~~~~~~~~~
|
||||
This field is optional. It is required only by the EQU directive.
|
||||
Specyfying this field definies a label. Defined label represents an integer
|
||||
of range -$ffff..$ffff.
|
||||
Name of label must begin in column 1 and can contain letters, digits
|
||||
and underscores (_). Digit can't be label's first character. Name of label
|
||||
can be as long as you want and all the characters are meaningful.
|
||||
In Quick Assembler only 6 leading characters were recognized
|
||||
and some programs may not compile well under X-Asm for this reason.
|
||||
Defining a label without using EQU makes it equal to current value
|
||||
of the origin counter. Label can't be redefined.
|
||||
|
||||
Operation field
|
||||
~~~~~~~~~~~~~~~
|
||||
Operation field is the only field which is always required.
|
||||
You have to put one or more spaces or tab characters between label
|
||||
and operation field. If no label is defined, line must start with a blank
|
||||
character. Operation field is always 3 letters long. It can be:
|
||||
a. a 6502 processor command
|
||||
b. a compiler directive
|
||||
c. a pseudo-command
|
||||
|
||||
a. 6502 command
|
||||
One of 56 well known processor commands.
|
||||
|
||||
b. compiler directive
|
||||
One of the following:
|
||||
|
||||
EQU - assign a value of expression to the label
|
||||
Note that label represents a number, not a text macro.
|
||||
Examples:
|
||||
five equ 5
|
||||
ten equ five+five
|
||||
|
||||
OPT - set assembling options
|
||||
Currently there are two options: listing generating and headers generating.
|
||||
You can turn any of these on or off.
|
||||
Examples:
|
||||
opt l- listing off
|
||||
opt h- headers off
|
||||
opt l+h- listing on, headers off
|
||||
Remember not to put a space between options:
|
||||
opt l+ h-
|
||||
is actually
|
||||
opt l+
|
||||
because h- is a comment.
|
||||
Default (if no opt specified) is opt l+h+.
|
||||
|
||||
ORG - set new origin counter
|
||||
Examples:
|
||||
org $600 code will be located starting from $0600
|
||||
table org *+100 'table' points to 100 bytes of uninitialized data
|
||||
New! You can set some options applied to new header (if headers are on):
|
||||
org $600
|
||||
rts
|
||||
org a:$601
|
||||
'a:' tells X-Asm to always make a header, even it is unnecessary (as in above).
|
||||
So by default X-Asm 2.0 does not generate unnecessary headers, distinct from
|
||||
QAsm and X-Asm 1.2.
|
||||
org f:$700
|
||||
'f:' works same as 'a:', but additionally tells to generate a $ff,$ff prefix
|
||||
before header. X-Asm adds it to the first header in file by default, so use
|
||||
this option only if you want the $ff's somewhere inside.
|
||||
|
||||
DTA - define data
|
||||
You may define:
|
||||
* numbers
|
||||
- bytes: b(200)
|
||||
- words: a(10000)
|
||||
- low bytes of words: l(511) defines byte 255
|
||||
- high bytes of words: h(511) defines byte 1
|
||||
You may enter many expressions in parentheses and combine different types
|
||||
of data in single line.
|
||||
You may also define a sinus table. Enter this expression:
|
||||
sin(centre,amp,size,first,last)
|
||||
where:
|
||||
- centre is a number which is added to every value of sinus
|
||||
- amp is the amplitude of sinus
|
||||
- size is the period of sinus
|
||||
- first,last define range of values in the table.
|
||||
They are optional. Default are 0,size-1.
|
||||
Example: dta a(sin(0,1000,256,0,63)) defines table of 64 words representing
|
||||
a quarter of sinus with amplitude of 1000.
|
||||
- real numbers: r(-1.23456e12)
|
||||
Real numbers are written in 6-byte Atari Floating-Point format. You can't
|
||||
combine reals with operators, as you can integers.
|
||||
* text strings
|
||||
- ASCII strings: c'Text' or c"Text"
|
||||
- ANTIC strings: d'Text' or d"It's something new!"
|
||||
A character string consists of any of characters surrounded by quotation
|
||||
marks. Within a string, a single quotation mark character is
|
||||
represented by two succesive quotation marks.
|
||||
Placing a '*' character after a string inverts bit 7 in every byte of string.
|
||||
Examples of DTA:
|
||||
dta b(2,5),a(1000,-1),l(12345,sin(0,127,256))
|
||||
dta d"ANTIC"*,c'It''s a string',b(155)
|
||||
|
||||
ICL - include another source file
|
||||
Specifies another file to be included in the assembly as if the contests of
|
||||
the referenced file appeared in place of the ICL statement. The included file
|
||||
may contain other ICL statements.
|
||||
Examples:
|
||||
icl 'macros.asx'
|
||||
icl 'c:\atari\xasm\fileio.asx'
|
||||
|
||||
END - end assembling of file
|
||||
Remaining part of the file is not assembled. If this statement does not occur,
|
||||
assembler stops assembling when encounters end of file.
|
||||
Example:
|
||||
end
|
||||
|
||||
INS - insert contents of file
|
||||
Copies every byte of specified file into object file and moves origin counter,
|
||||
as if these bytes were defined with DTA.
|
||||
Examples:
|
||||
ins 'picture.raw'
|
||||
ins 'tables.dat'
|
||||
New! You may specify range of inserted file. Syntax is:
|
||||
ins 'file'[,offset[,length]]
|
||||
First byte in file has offset 0.
|
||||
If offset is negative, it is counted from the end of file.
|
||||
ins 'file',-256 inserts last 256 bytes of file
|
||||
ins 'file',10,10 inserts bytes 10..19 of file
|
||||
|
||||
RUN - generate run address
|
||||
The Atari executable program should have run address specified. Remember that
|
||||
a program may be loaded in many areas of memory and started from any address.
|
||||
run addr
|
||||
is equivalent to:
|
||||
org $2e0
|
||||
dta a(addr)
|
||||
Examples:
|
||||
run start
|
||||
run program
|
||||
|
||||
INI - generate init address
|
||||
The Atari executable program may have some routines which are executed during
|
||||
loading process. There may be many init blocks in one file.
|
||||
Examples:
|
||||
ini init
|
||||
ini showpic
|
||||
|
||||
ERT - generate error if expression is true
|
||||
Examples:
|
||||
ert *>$c000
|
||||
ert len1>$ff||len2>$ff
|
||||
|
||||
IFT - assemble if expression is true
|
||||
ELS - else
|
||||
EIF - end if
|
||||
Example:
|
||||
noscr equ 1
|
||||
ift noscr
|
||||
lda #0
|
||||
els
|
||||
lda #$22
|
||||
eif
|
||||
sta $22f
|
||||
|
||||
c. pseudo-command
|
||||
It is something like built-in macro. It replaces two or more standard
|
||||
processor commands. Note that it is not an illegal instruction and works
|
||||
on typical 6502.
|
||||
|
||||
ADD - addition without carry
|
||||
If you ever programmed 6502, you must have noticed that you had to use a CLC
|
||||
before ADC for every simple addition.
|
||||
X-Asm can do it for you. ADD simply replaces two instructions: CLC and ADC.
|
||||
|
||||
SUB - subtraction
|
||||
It is SEC and SBC.
|
||||
|
||||
JNE, JEQ, JCC, JCS, JPL, JMI, JVC, JVS - conditional jumps
|
||||
They are a kind of 'long' branches. While standard branches (BNE, BEQ) have
|
||||
range of -128..+127, these jumps have range of all 64 kB.
|
||||
For example: a JNE DEST is replaced with:
|
||||
beq *+5
|
||||
jmp dest
|
||||
|
||||
INW - increment word
|
||||
It is a 16-bit memory increment command. An INW DEST will be replaced by:
|
||||
inc dest
|
||||
bne _skip
|
||||
inc dest+1
|
||||
_skip equ *
|
||||
The '_skip' label is not declared of course.
|
||||
|
||||
MVA, MVX, MVY - move byte using accumulator, X or Y
|
||||
These pseudo-commands require two operands.
|
||||
mva source dest = lda source : sta dest
|
||||
mvx source dest = ldx source : stx dest
|
||||
mvy source dest = ldy source : sty dest
|
||||
|
||||
MWA, MWX, MWY - move word using accumulator, X or Y
|
||||
Also require two operands. They are something like combination of two MV*'s:
|
||||
one to move low byte, and the other to move high byte.
|
||||
You can't use indirect nor pseudo addressing modes with MW*.
|
||||
Destination must be absolute address (indexed or not).
|
||||
When source is also absolute, a MW* SOURCE DEST will be:
|
||||
mv* source dest
|
||||
mv* source+1 dest+1
|
||||
When source is immediate, a MW* #IMMED dest will be
|
||||
mv* <immed dest
|
||||
mv* >immed dest+1
|
||||
but when <IMMED = >IMMED and IMMED is not forward-referenced,
|
||||
X-Asm uses optimization:
|
||||
mv* <immed dest
|
||||
st* dest+1
|
||||
|
||||
Operand
|
||||
~~~~~~~
|
||||
It depends on the operation field. Some statements don't need an operand
|
||||
or need two operands.
|
||||
|
||||
6502 commands require operand depending on the addressing mode.
|
||||
Addressing modes should be entered in standard convention except
|
||||
the accumulator addressing mode, which should be marked with a '@' character
|
||||
(as in Quick Assembler).
|
||||
|
||||
There are two extra immediate addressing modes: < and >, which use low/high
|
||||
byte of word is used rather than byte value.
|
||||
|
||||
In absolute addressing modes, X-Asm examines expression and uses zero-page
|
||||
addressing mode if it thinks it is possible to do it. You may override it
|
||||
with 'a:' and 'z:' prefixes.
|
||||
|
||||
Examples:
|
||||
nop
|
||||
asl @
|
||||
lda >$1234 assembles to lda #$12
|
||||
lda $100,x
|
||||
lda a:0 generates 16-bit address
|
||||
jmp ($0a)
|
||||
lda ($80),y
|
||||
|
||||
New! X-Asm 2.0 brings pseudo addressing modes. They are similar to
|
||||
pseudo-commands and you may use them as standard addressing modes
|
||||
in all 6502 commands and pseudo-commands, excluding MW*:
|
||||
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
|
||||
|
||||
Problems
|
||||
--------
|
||||
These notes may help you solve problems:
|
||||
|
||||
* No spaces are allowed within a field.
|
||||
label equ 1 + 2
|
||||
causes label to be equal 1 ('+ 2' is treated as a comment).
|
||||
|
||||
* < and > represent addressing modes rather than LOW and HIGH operators.
|
||||
You specify 'lda <table', not 'lda #<table' like in most 6502 assemblers.
|
||||
|
||||
* Label definition does not include a colon
|
||||
label: lda ^4b ERROR - colon after label name
|
||||
|
||||
* Exactly one run address should be specified
|
||||
Remember that unlike in other assemblers
|
||||
end start
|
||||
does not tell the assembler that 'start' is the run address (it is a comment).
|
||||
You must specify the run address with RUN directive.
|
||||
|
||||
* X-Asm reads source twice (in pass 1 and pass 2)
|
||||
This allows forward references, but not too complex.
|
||||
Keep in mind that assembler should know all the values in second pass.
|
||||
Example:
|
||||
two equ one+one This value is known in 2nd pass only
|
||||
one equ 1 This value is known as early as in 1st pass
|
||||
These values can be fixed in 2 passes.
|
||||
But if you insert following statement as first line:
|
||||
three equ one+two
|
||||
X-Asm will generate an error because it doesn't know the value of 'three' in
|
||||
second pass.
|
||||
(sorry for v1.2 users: EQU forward reference didn't work at all).
|
||||
|
||||
* X-Asm displays only first error
|
||||
When you correct one error don't be surpised if you get another one.
|
||||
|
||||
* If you encounter X-Asm works improperly, please let me know.
|
||||
|
||||
===
|
Loading…
x
Reference in New Issue
Block a user