The assembler
NOTE: This version of XA is based from the original source code when the development was abandonned around 1998.
Since then, the development of the official version had started again and then stopped again.
You can find the other official releases (2.3.x) on these two places:
- http://www.floodgap.com/retrotech/xa/
- https://github.com/fachat/xa65
The assembler contains only a single programm called "xa". It takes one or more Source files into one object file, that can directly be used. But the assembler also has a mode to produce relocatable files, conforming to the 'o65' fileformat (See fileformat.txt).
Call:
xa [options] Source1 [Source2 ...]Object: this is the name, the output (object) file gets Error: Here you will find the Error listing. Label: this is the label list
'-C' gives error codes when using CMOS-opcodes. Default is not to complain. '-c' do not produce o65 executable, but object files that can contain undefined references. '-cc' almost identical to '-c' except the result is usable with CC65 tools. '-v' go into verbose mode '-R' do not produce absolute code, but do relocation and all that. '-o filename' set output filename '-e filename' set errorlog filename '-l filename' set labellist filename '-r' add crossreference list to labellist output (i.e list of filename/line where label is used) '-M' This option used to allow ':' to appear in comments after a semicolon (MASM mode), but this is now the default behavior. '-b? adr' set segment start address for ? = t(ext), d(ata), b(ss) or z(ero) segment. '-A adr' the _file_ starts at adr in a ROM, then the text segment need not be relocated. That of course only works, if the data/bss/zero segments are not occupied by other programs. '-G' omit writing the exported globals to the file. '-B' Show lines with '.(' or '.)' pseudo opcodes '-Llabel' defines 'label' as absolute, undefined reference '-DDEF=TEXT' define a preprocessor replacement '-Ipath' additional include path for include files. Is evaluated before the XAINPUT environment variable. One path per '-I', multiple '-Ipath' allowed.Omitting the errorfile or labelfile Parameter will cause xa to not write these files. Using '-x' will cause xa to take the name of the first source file and change the extension (on an Atari there is only one, like in DOS) to 'obj', 'err' and 'lab' respectively - if the old behaviour is selected with the '-x' option or the files are defined with "-l" and "-e". If no output file is given, "a.o65" is used.
The label file is a readable ASCII-file and lists all the labels together with their block-count (see below) and their address. The error file lists the version of the assembler, date and time of the assembler run, all the error messages and the stuff being printed with #echo and #print and last but not least a statistics of used resources.
Values or Addresses can be expressed by arithmetik expressions with hierachy and bracket. The following operands are understood:
123 -decimal $234 -hexadecimal &123 -octal %010110 -binary * -program counter "A" -ASCII-code labelx -label -(lab1+1) -expressionThe following operands can be used (third column is priority):
+ -addition 9 - -subtraction 9 * -multiplication 10 / -integer-division 10 << -shift left 8 >> -shift right 8 >=,=> -more or equal 7 <=,=< -less or equal 7 < -less 7 > -more 7 = -equal 6 <>,>< -not equal 6 && -logical AND 2 || -Logical OR 1 & -Bitwise AND 5 | -Bitwise OR 3 ^ -Bitwise XOR 4Operators with higher priority are evaluated first. Brackets can be used as usual.
Valid expressions are, e.g.:
LDA base+number*2,xFor Addressing modes that do not start with a bracket, you can even use a bracket at the beginning of an expression. Otherwise try this:
LDX (1+2)*2,y ; Wrong! LDX 2*(1+2),y ; Right!Before an expression you can use these unitary operators:
< Gives the low byte of the expression > Gives the high byte LDA #<adresseSingle Assembler statements are being separated by a ':' (You remember the C64 :-) or a newline. Behind Each statement, separated by a ';' you can write some comments. The next colon or a newline ends the comment and starts a new statement. In MASM compatibility mode ('-M' command line option), then a colon in a comment is ignored, i.e. the comment lasts till the newline.
Pseudo opcodes, Block structures and where Labels are valid
In addition to the 6502 opcodes you have the following Pseudo opcodes:-
'.byt' and '.asc' are identical and save values to the memory (object file) bytewise.
.byt value1,value2,value3, ... .asc "text1","text2", ...
-
'.word' does the same with words (2 Bytes).
.word value1,value2, ...
-
'.dsb' fills a block with a given length with the value of fillbyte.
If fillbyte is not given, zero is taken.
.dsb length ,fillbte
-
'*=' changes the programm counter.
The programm counter is not saved to the file as no rewind is being done.
Just the internal counter is reloaded.
If a value is given when the assembler has been started in relocation mode
('-R command line option), the assembler goes into no-relocation mode, i.e
assembles everything without creating relocation table entries.
For '*=' without a value, the assembler switches back to relocation mode.
The absolute code is 'embedded' in the text segment, so the text segment
program counter is increased by the length of the absolute code.
One usage of this feature is for example to set the adress of buffers in BSS in the overlay memory on the oric:
.bss *=$C000 BigBuffer .dsb 256
- '.(' opens a new 'block'. All labels in a block are local, i.e. are only visible from inside the block - including sub-blocks. An error is returned if a label is defined that is already defined 'above'.
- With '.)' the block is closed. You can have a stack of up to 16 blocks in each other (i.e. 16 times '.(' before the first '.)' will work, 17 not).
-
'.text', '.data', '.bss', '.zero' switch between the different segments.
- The text segment is where the code goes in.
- The data segment is where some initialized data goes in (it's actually like a second text segment).
- The data segment might be allocated separated from the text segment.
- The contents of the bss and the zero segment are not saved, just the labels are evaluated. Here goes the uninitialized data stuff.
- The zero segment allows allocation of zeropage space, bss is normal address space.
-
'.align' aligns the current segment to a byte boundary given by the value.
Allowed values are 2, 4, and 256.
When using relative mode, the align value is written to the file header, such that relocation keeps the alignment.
Note: It seems that this directive is totaly bugged, at least I never managed to ge it to do what I wanted to do. Since one of the most common use of allignement on the 6502 is to allign data on a multiple of 256 bytes (page), it's possible to hack around by using this work around:
.dsb 256-(*&255) // The program counter from this point is alligned on the next multiple of 256
-
'.fopt' works like ".byte", but saves the bytes as a fileoption (see
fileformat.txt). The length is computed automatically, so the first
byte in the ".fopt" list of values should be the type.
For example, the following line sets the filename for the object file.
.fopt 0, "filename", 0
Labels
A label is defined by not being an opcode:label1 LDA #0 ; assignes the programm counter label2 =1234 ; explicit definition label3 label4 label5 ; implicit programm counter label6 label7 = 3 ; label6 becomes the program counter, while ; label7 is set to 3 label8: sta label2 ; As ':' divides opcodes, this is also ; workingYou can use more than one label for definition, except for explicit definition.
- Labels are case sensitive.
- If a label is proceeded by a '+', this label is defined global.
- If a label is proceeded by a '&', this label is defined one level 'up' in the block hierachy, and you can use more than one '&'.
- Redefinition of a label is possible by proceeding it with a dash '-':
-sysmem +=4 ; here you can use ==, +=, -=, *=, /=, &=, |= -syszp =123
Preprocessor
The preprocessor is very close to the one of the language C. So in addition to the ';'-comments you can also use C-like comments in '/*' and '*/'. Comments can be nested.
#include "filename" includes a file on exactly this position. if the file is not found, it is searched using XAINPUT. #echo comment gives a comment to the error file. #file "filename" Set the internal line counter in order to get correct line numbers at link phase #print expression prints an expression to the error file (after preprocessing and calculating) #printdef DEFINED prints the definition of a preprocessor define to the error file. #define DEF text defines 'DEF' by 'text' #ifdef DEF The source code from here to the following #endif or #else is only assembled if 'DEF' is defined with #define. #else just else... (optionally) #endif ends an #if-construct. This is a must to end #IF* #ifndef DEF .... if DEF is not defined #if expression .... if expression is not zero #iflused label .... if a label has already been used #ifldef label .... if a label is already defined#iflused and #ifldef work an labels, not on preprocessor defs! With these commands a kind of library is easily built:
#iflused label #ifldef label #echo label already defined, not from library #else label lda #0 .... #endif #endifYou can have up to 15 #if* on stack before the first #endif
You can also use #define with functions, like in C.
#define mult(a,b) ((a)*(b))The preprocessor also allows continuation lines. I.e. lines that end with a '\' directly before the newline have the following line concatenated to it.
Issue #22: .data section not working as expected
Details: If not specified, the .data section should by default start after the end of the .text section, they also should be saved in the binary, but apparently in non-relocatable mode this appears to be broken.
Issue #19: MASM compatibility
Details: XA now handles correctly the ":" character in comments. The -M (MASM compatibility) option should be replaced by something that does nothing. (See: topic)
Fixed in OSDK 1.10
Details: o65 object files generated by XA are not compatible with CC65 and require some binary patching. (See: topic)
Fixed in OSDK 1.9
Details: The number of defines supported by XA is limited to 2340, expanding the value to something significantly larger would be welcome.
Fixed in OSDK 1.10
Details: Add a new parameter,OSDKXAPARAMS, which can be used to pass additional parameters to the assembler. A typical usage would be to pass additional defines using the -D notation.
Fixed in OSDK 1.8
Details: At the moment XA allows any 6502 instructions, such as PLX, PLY, PHX, PHY which are not available in the NMOS version of the 6502 used on the Oric. Ideally they should be refused by default, except if allowed from a command line flag.
comments powered by Disqus