X-Assembler version 2.2

by Fox/Taquart


INTRODUCTION  USAGE  SYNTAX  FAQ  BACK

The X-Assembler is an cross-assembler, which generates code for the 6502 processor. It is 99% compatible with Quick Assembler on 8-bit Atari.

CHANGES

Version 2.2

Version 2.0

Version 1.2


INTRODUCTION  USAGE  SYNTAX  FAQ  BACK

System requirements

Creating a source program

Source file should be plain ASCII file. Although different EOLs are supported, you would probably prefer CR/LF EOLs because of text editor.
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, which 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

You run assembler from DOS prompt with following syntax:
XASM source [options]

source is name of source file. If no extension given, the .ASX is added by default.

Optional options are:

/c
Enable listing false conditionals.
By default lines skipped because of false condition are not listed.

/e
Enable setting environment variables when error occurs.
With this option, X-Asm sets two environment variables: ERRFILE and ERRLINE. They may be used in a batch file to locate error and set editor on it. For example, in my batch file I use such construction:
XASM %1 /e

IF NOT ERRORLEVEL 1 GOTO ok

NCE +%ERRLINE% %ERRFILE%

NCE stands for Norton Classic Editor.

If there was no error, variables point at last warning. If no warning occured, they are removed from the environment.

/i
Disable listing included source.
Only main source file will be listed.

/l[:fname]
Enable generating listing. If no fname given, listing is written to source.lst.

/n
Check source and object modification times and assemble only if source is newer than object file. X-Asm does NOT check included nor inserted files but only main source, so be careful with this option.

/o:fname
Specify object name. Default is source.obx.

/s
Disable converting spaces to tabs in listing. 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 stops on 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:

Label table structure

Line of label table includes:

INTRODUCTION  USAGE  SYNTAX  FAQ  BACK

Lines of source code may be: Comment lines must have one of the following characters in the FIRST column of the line: * ; |

Expressions  Statements

Expressions are numbers combined with operators and brackets. You should use square brackets, because parentheses are reserved for 6502 indirect addressing.

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
  • an ASCII character
'a' or "a"
  • an origin counter
*
  • a hardware register
^31
An abbreviation of Atari hardware register:
^0x means $d00x
^1x means $d01x
^2x means $d20x
^3x means $d30x
^4x means $d40x
where x is a hexadecimal digit.
  • an op-code
{lda #0}
Byte op-code of instruction inside braces. Operand is discarded and is necessary only for identifying addressing mode. Instruction should begin right after left brace and right brace should immediately follow the operand or the command in implied addressing mode.

Operators

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.

Expressions  Statements

A statement is divided into fields: 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 starts from first character of line, without any blank characters before. It has two applications:
You can not define a label in line which you repeat.

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 consists of one or two instructions. The latter case is called instructions pairing, because a pair of instructions have shared operand. You separate instructions with a colon.
Example:
 adc:sta $80

is equivalent to
 adc $80

 sta $80

Single instruction always consists of 3 letters. It can be:
  1. 6502 command
    One of 56 well known processor commands.

  2. 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
    
    here equ *
    
    
    OPT - set assembling options
    Currently there are two options: listing generating and headers generating. You can turn any of these on or off.
    Default (if no OPT specified) is opt l+h+.
    Examples:
     opt l-    listing off
    
     opt h-    headers off
    
     opt l+h-  listing on, headers off
    
    
    ORG - set new origin counter
    You can set some options applied to new header (if headers are on):
    • a: tells X-Asm to always make a header, even it is unnecessary, like in ORG *.
    • 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.
    Examples:
     org $600
    
     org f:$700
    
    table org *+100
    
    
    In the latter example table points to 100 bytes of uninitialized data (note label is assigned to * before ORG directive is executed).

    DTA - define data
    There are various data types:
    • 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, separating things with commas.
        You may also define a sinus table. Syntax is:
        sin(centre,amp,size,first,last)
        where:
        • centre is a number which is added to every sinus value
        • 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"Text"
      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 high bit 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. The .ASX extension is added if none given.

    Examples:

    
     icl 'macros.asx'
    
     icl 'c:\atari\xasm\fileio'
    
    
    END - end assembling 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.
    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.
    Examples:
    
     ins 'picture.raw'
    
     ins 'file',-256   insert last 256 bytes of file
    
     ins 'file',10,10  insert bytes 10..19 of file
    
    
    RUN - generate run address
    The Atari executable program should have run address specified. 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
    With these directives you can construct fragments which are assembled when a condition is met. Conditional constructions can be nested.
    Example:
    noscr equ 1
    
     ift noscr
    
     lda #0
    
     els
    
     lda #$22
    
     eif
    
     sta $22f
    
    
    Above example can be rewritten using line repeating feature:
    noscr equ 1
    
    :noscr<>0 lda #0
    
    :noscr=0 lda #$22
    
     sta $22f
    
    
  3. pseudo-command
    It is something like built-in macro. 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 replaces two instructions: CLC and ADC.

    SUB - subtraction
    It is SEC and SBC.

    RCC, RCS, REQ, RMI, RNE, RPL, RVC, RVS - conditional repeat
    They are branches to the previous instruction. They take no operand, because the branch target is the address of previously assembled instruction.
    Example:
     ldx #0
    
     mva:rne $500,x $600,x+
    
    
    The example code copies memory $500-$5ff to $600-$6ff. With standard 6502 commands only it would be:
     ldx #0
    
    loop lda $500,x
    
     sta $600,x
    
     inx
    
     bne loop
    
    
    SCC, SCS, SEQ, SMI, SNE, SPL, SVC, SVS - conditional skip
    They are branches over the next instructions. No operand is required, because the target is the address of instruction following the next instruction.
    Example:
     lda #40
    
     add:sta $80
    
     scc:inc $81
    
    
    In the above example word variable $80 is incremented by 40.
    Nor conditional repeat nor skip pseudo-commands require operand, thus they can be paired with any other command.

    JCC, JCS, JEQ, JMI, JNE, JPL, 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.
    Example:
     jne dest
    
    
    is equivalent to:
     seq:jmp dest
    
    
    INW - increment word
    It is a 16-bit memory increment command.
    Example:
     inw dest
    
    
    is equivalent to:
     inc dest
    
     sne:inc dest+1
    
    
    MVA, MVX, MVY - move byte using accumulator, X or Y
    Any 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
    
    
    MWA, MWX, MWY - move word using accumulator, X or Y
    They also require two operands and are combinations 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
    
    
    When <immed equals >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 any operand, other 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 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

There are also pseudo addressing modes, which are similar to pseudo-commands. You may use them as standard addressing modes in all 6502 commands and pseudo-commands excluding MWA, MWX and MWY only:
 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

Comment

Comment in a statement does not start from any special character like ; for example. Comment field is implied when appropriate number of operands was taken.


INTRODUCTION  USAGE  SYNTAX  FAQ  BACK