

                                 ACME

         ...the ACME Crossassembler for Multiple Environments

                       --- Quick  reference ---


This file should give you a basic overview. More specialized stuff
like forcing a specific addressing mode is discussed in extra files
("AddrModes.txt" in this case).


----------------------------------------------------------------------
Section:   Example of what an ACME source code file looks like
----------------------------------------------------------------------

;--- Example code fragment, start ---

		!to "tiny.o", cbm	; set output file and format
		* = $c000		; set program counter

	CLEAR = 147		; a global symbol definition
!addr	basout = $ffd2		; another one, marked as an address

		; a string output loop:
		ldx #0
		beq +			; enter loop

-			jsr basout	; output character
			inx		; advance pointer
+			lda .string, x	; get character
			bne -		; check whether last
		rts
.string		!pet "Dumb example", 13, 0

;--- Example code fragment, end ---


Here's the same fragment again, now with some additional info:

;--- Example code fragment, start ---

		!to "tiny.o", cbm	; set output file and format
; This is a pseudo opcode to select the output filename and format.
; This can also be done using the command line options "-o" and "-f",
; respectively.
		* = $c000		; set program counter
; This can also be done using the command line option "--setpc".

	; some global symbol definitions
	CLEAR = 147	; this is a simple constant
; Now "CLEAR" is defined as a global symbol having the value 147.
!addr	basout = $ffd2	; this gets marked as an address
; Now "basout" is defined as a global "address" type symbol having the
; value $ffd2.
	; The distinction between addresses and non-addresses only
	; matters when the type check system gets activated using
	; the "-Wtype-mismatch" switch. Then, a line like
	; "lda CLEAR" would trigger a type mismatch warning because
	; of the missing '#' character.

		; a string output loop:
		ldx #0
		beq +			; enter loop
; "+" is an anonymous forward label. Other ones are "++", "+++", etc.
; They can be used like any other symbol, but they always reference
; their *NEXT* definition. This saves having to think of names for
; unimportant labels. As the label's value is not defined yet, ACME
; will need to perform a second pass.
-			jsr basout	; output character
; "-" is an anonymous backward label. Other ones are "--", "---", etc.
; They can be used like any other symbol, but they always reference
; their *PREVIOUS* definition. This saves having to think of names for
; unimportant labels. In the line above, the value of "-" is set to
; the current program counter.
			inx		; advance pointer
+			lda .string,x	; get character
; Here the value of "+" is set to the current program counter.
; ".string" is a local symbol (because its name starts with a '.'
; character), but as its value is not defined yet, ACME will need to
; perform a second pass.
			bne -		; check whether last
; Here the last definition of the anonymous "-" label is referenced.
		rts
.string		!pet "Dumb example", 13, 0
; Now the value of the local label ".string" is set to the current
; program counter. All label values are defined now, so after having
; done the second pass, the binary will be saved. The "!pet" pseudo
; opcode stores its string argument in PetSCII encoding to memory,
; followed by the given byte values.

;--- Example code fragment, end ---

As you can see, pseudo opcodes are prefixed with an exclamation mark.
That's non-standard, but: Backwards compatibility is the root of all
evil. :)

Summary about symbols:

There are global symbols (their names starting with a letter or an
underscore character). These can be accessed throughout the whole
assembly.
Then there are local symbols (their names starting with a '.'
character). These can only be accessed from inside the macro or zone
they were defined in (for more about macros and zones, see the file
"AllPOs.txt").
There are also "cheap locals": their names start with an '@'.
The area where these can be accessed is limited automatically by the
previous and the following global label (cheap locals are "cheap"
because you don't have to put in any extra work to limit their range).
And then there are anonymous labels (their names being sequences of
either '-' or '+' characters). They are also local (bound to their
macro/zone), but in addition to that, the "-" labels can only be used
for backward references, while the "+" labels can only be used for
forward references.
In contrast to global and local labels, anonymous labels can not be
defined explicitly (as in SYMBOL = VALUE).
Each macro call automatically gets its own scope for local symbols.

Save the given example source code to a file called "tiny.a" and start
acme by typing

    acme tiny.a

ACME will then parse the file and report any errors. An output file
will only be generated if there were no errors and if an output
filename has been given.

After assembly, the example program can be run on a C64 using

    LOAD "tiny.o", 8, 1
    SYS 49152

Note that ACME does not include any routines for transferring data to
a C64. Such tools exist on almost every platform, and I didn't want
ACME to become bloatware.


----------------------------------------------------------------------
Section:   The pseudo opcodes
----------------------------------------------------------------------

A list with information on how to use all the Pseudo Opcodes can be
found in the file "AllPOs.txt". Here's just a short overview:

!byte   !word   !24   !32   !fill   !align
...for directly placing values into the output file.

!zone   !symbollist
...for defining the scope of local symbols and saving global symbols.

!convtab   !pet   !raw   !scr   !scrxor   !text
...for converting and outputting strings.

!do   !endoffile   !for   !if   !ifdef   !ifndef   !set   !while
...for flow control; looping assembly and conditional assembly.

!binary   !source   !to
...for handling input and output files.

!pseudopc
...for offset assembly.

!initmem   *=
...for segment assembly.

!macro   +
...for defining and calling macros.

!cpu   !al   !as   !rl   !rs
...for CPU support, especially the 65816 processor.

!warn   !error   !serious
...for generating warnings, errors and serious errors.

!address
...to mark symbols as addresses, for the optional type check system.


----------------------------------------------------------------------
Section:   Command line arguments
----------------------------------------------------------------------

The command line syntax for calling acme is quite simple:

    acme [options] [files]

Available options are:
    -h, --help             show this help and exit
        This is more or less useless, because the help is also shown
        if ACME is run without any arguments at all.

    -f, --format FORMAT    set output file format
        Use this with a bogus format type to get a list of all
        supported ones (as of writing: "plain", "cbm" and "apple")
    -o, --outfile FILE     set output file name
        Output file name and format can also be given using the "!to"
        pseudo opcode. If the format is not specified, "!to" defaults
        to "cbm", while the command line option defaults to "plain".

    -r, --report           set report file name
        This creates a text listing containing the original line
        number, the resulting memory address, the byte value(s) put
        there and the original text line from the source file.

    -l, --symbollist FILE  set symbol list file name
        This can also be given using the "!symbollist"/"!sl" pseudo
        opcode. The switch was called "--labeldump" in older versions,
        that name still works, too.

    --vicelabels FILE      set file name for label dump in VICE format
        The resulting file uses a format suited for the VICE emulator.

    --setpc VALUE          set program counter
        This can also be given in the source code using "* = VALUE".

    --cpu CPU_TYPE         set target processor
        This can be changed in the source code using the "!cpu" pseudo
        opcode. Defaults to 6502.
        Use this with a bogus cpu type to get a list of all supported
        ones.

    --initmem VALUE        define 'empty' memory
        This can also be given using the "!initmem" pseudo opcode.
        Defaults to zero.

    --maxerrors NUMBER     set number of errors before exiting
        If not given, defaults to 10.

    --maxdepth NUMBER      set recursion depth for macro calls and !src
        The default value for this is 64.

    --ignore-zeroes        do not determine number size by leading zeroes
        Normally, using leading zeroes forces ACME to generate
        oversized addressing modes, like 3-byte absolute instructions
        instead of 2-byte zero page instructions.
        Using this CLI switch disables this behavior.

    --strict-segments      turn segment overlap warnings into errors
        When changing the program counter, segment overlap warnings may
        be generated. Using this CLI switch turns those warnings into
        errors (which is recommended).
        This strict behavior may become the default in future releases!

    -vDIGIT                set verbosity level
        Sets how much additional informational output is generated.
        Higher values mean more output:
        acme -v0 source.a
            This is the default: No additional output is generated,
            ACME will only display warnings and errors.
        acme -v1 source.a
            Now the start and end addresses of the generated output
            file are displayed, along with its size (a CBM-style
            "load address" is *not* counted).
        acme -v2 source.a
            In addition to the "-v1" output, ACME will announce each
            pass, will show amount and offset of "!binary" loads, and
            show start and end addresses and size of each segment.
        acme -v3 source.a
            In addition to the "-v2" output, ACME will now announce
            each source file.

    -DSYMBOL=VALUE         define global symbol
        This option is useful if you build your projects using
        Makefiles: "-DSYSTEM=64" could build the C64 version while
        "-DSYSTEM=128" could build the C128 version of the software
        (using conditional assembly in your source code file).

    -I PATH/TO/DIR         add search path for input files
        This option allows to add a directory to the search list for
        input files. If an input file cannot be found in the current
        working directory, all directories in the search list are
        tried (the first match is used).

    -W                     fine-tune amount and type of warnings
        -Wno-label-indent
            Disables warnings about labels not being in the leftmost
            column.
        -Wno-old-for
            Disables warnings about the old "!for" syntax and at the
            same time enables warnings about the _new_ "!for" syntax.
            Internally, this does exactly the same as what happens
            when the "--dialect 0.94.8" CLI switch is used...
        -Wno-bin-len
            Do not complain about unusual number of digits in a binary
            literal.
        -Wtype-mismatch
            Enables type checking system (warns about wrong types).

    --use-stdout           fix for 'Relaunch64' IDE
        With this option, errors are written to the standard output
        stream instead of to the standard error stream.

    --msvc                 output errors in MS VS format
        This changes the format of the error output to that used by
        a certain commercial IDE.

    --color                uses ANSI color codes for error output
        If your terminal emulation supports ANSI escape codes, use
        this option to have warnings and errors displayed in color.

    --fullstop             use '.' as pseudo opcode prefix
        This changes the prefix character used to mark pseudo opcodes
        from '!' to '.' (so sources intended for other assemblers can
        be converted with less effort).

    --dialect VERSION      behave like different version
        This CLI switch tells ACME to mimic the behavior of an older
        version. Use this with a bogus version to get a list of all
        supported ones.

    --test                 enable experimental features
        This is for people who want to help test new features before
        they are officially announced.

    -V, --version          show version and exit.

Platform-specific versions of ACME might offer more options.
Since version 0.89, ACME accepts more than one top-level-filename
given on the command line.


----------------------------------------------------------------------
Section:   The expression parser
----------------------------------------------------------------------

ACME has a relatively powerful maths parser. This parser is used
whenever ACME expects to read a value. Supported operations include
addition, subtraction, multiplication, divisions, comparisons, shifts,
negation, boolean operations and some assembler-specific stuff like
extracting the "low byte", the "high byte" or the "bank byte" of a
value.
Calculations are done using either signed (at least 32-bit) integer
arithmetic or floating point arithmetic using the C "double" data
type. Symbol values are stored the same way.


This is a list of the value formats currently known by ACME:

Examples        Notes
---------------------------------------------------------------------
128             a decimal value, integer
128.5           a decimal value, floating point
$d011           hexadecimal values are indicated by either a
0xffd2              leading "$" or a leading "0x".
&1701           an octal value, indicated by "&"
%1010           binary values are indicated by either a leading "%"
%....#...           or a leading "0b". In binary values, you can
0b01100110          substitute the characters "0" and "1" by "." and
                    "#" respectively. This way the values are much
                    more readable, especially when building bitmapped
                    objects (like C64 sprites or fonts) in your source
                    code.
'p'             single characters in single quotes are converted to
                    their character code. The actual numeric value
                    depends on the current conversion table chosen
                    using the "!ct" pseudo opcode.
"player 2"      double quotes indicate text strings. See below for
                    more information on single vs. double quotes.
[2, 3, 5, 7]    brackets indicate lists. These are useful to group
[0, [x, y], 9]      data, for example when passing an arbitrary number
                    of arguments to a macro.
poll_joy2       a global symbol
.fail           a local symbol, indicated by leading "."
@loop           a "cheap local", indicated by leading "@"
*               the current program counter. During offset assembly,
                    "*" gives the value of the "Pseudo PC". Just to
                    make sure: The value of the program counter is
                    always the value that was valid at the start of
                    the current statement, so
                        !word *, *, *, *
                    will give the same value four times. I think most
                    assemblers do it this way.

In older versions of ACME, 'x' and "x" were the same thing, namely the
character code of the letter x using the currently selected encoding
table.
Since release 0.97, anything in single quotes gives the character code
(as before), while anything in double quotes is treated as a string
object. To be compatible to those older versions, ACME keeps accepting
one-char strings in a lot of places where actually single characters
are expected.


This is a list of the operators currently known by ACME:

Priority Example      Meaning                       Alias         Note
----------------------------------------------------------------------
 16      is_number(v) these three functions return 1               *3
 16      is_list(v)       if v is the correct symbol               *3
 16      is_string(v)         type and 0 otherwise                 *3
 16      len(v)       length of list or string                     *2
 16      sin(v)       trigonometric sine function
 16      cos(v)       trigonometric cosine function
 16      tan(v)       trigonometric tangent function
 16      arcsin(v)    inverse of sin()
 16      arccos(v)    inverse of cos()
 16      arctan(v)    inverse of tan()
 16      address(v)   mark as address               addr(v)
 16      int(v)       convert to integer
 16      float(v)     convert to float
 15      &symbol      "unpseudopc" symbol (see docs on "!pseudopc")
 14       v[w]        access v with index w                        *2
 13         !  v      bit-wise complement           NOT
 12      v  ^  w      to the power of
 11         -  v      negate
 10      v  *  w      multiply
 10      v  /  w      divide
 10      v DIV w      integer divide
 10      v  %  w      remainder of DIV              MOD
  9      v  +  w      add                                          *3
  9      v  -  w      subtract
  8      v <<  w      shift left                    ASL, LSL
  8      v >>  w      arithmetic shift right        ASR
  8      v >>> w      logical shift right           LSR
  7         <  v      low byte of
  7         >  v      high byte of
  7         ^  v      bank byte of
  6      v <=  w      lower or equal
  6      v  <  w      lower than
  6      v >=  w      higher or equal
  6      v  >  w      higher than
  5      v !=  w      not equal                     <>,  ><        *3
  4      v  =  w      equal                                        *3
  3      v  &  w      bit-wise AND                  AND
  2                   bit-wise exclusive OR         XOR
  1      v  |  w      bit-wise OR                   OR

Notes:
"*2" means this operator only works on lists and strings.
"*3" means this operator works on all three data types (numbers, lists
and strings).
All other operators only work on numbers.

Operations with higher priority are done first. Of course you can
change this using parentheses.
Note that though there are operators to extract the "low byte", the
"high byte" and the "bank byte", there is no operator to extract the
fourth byte. If you want to access that, shift it down using ">>>" or
"LSR".
In cases where it's not clear which operator was wanted, ACME takes
the longest possible one:
	v<>w	...checks for "v not equal w"
	v< >w	...checks for "v smaller than high byte of w"
So you may have to separate operators with spaces to make sure ACME
does what you want.
The "power-of" operator is right-associative, so a^b^c means a^(b^c).

Calculating 0^0 (zero to the power of zero) will give 1. If
you don't know why I'm telling you this, ask a mathematician. :)


----------------------------------------------------------------------
Section:   Almost, but not quite, complete syntax
----------------------------------------------------------------------

Every ACME source code file consists of a non-negative number of
"lines". The lines have to be separated from each other using CR, LF
or CRLF characters.

Every line consists of a non-negative number of "statements" and an
optional comment. Statements have to be separated from each other
using colon (":") characters, the comment has to be prefixed with a
semicolon (";") character or two slashes ("//").

Every statement consists of an optional "label" and an optional
"command". These are separated from each other using any number of
SPACE or TAB characters. If a label has blanks before it, a warning is
issued (to spot typing errors - see Errors.txt for more info).

Every symbol name consists of these characters: "a" to "z", "A" to
"Z", "0" to "9", the underscore character "_" and all characters with
values beyond 127. The first character must not be a digit though. But
it can be '.' or '@', making the symbol a local one.
Local symbols beginning with '.' are only valid inside the current
zone (marked using the "!zone" pseudo opcode) or the current macro.
Local symbols beginning with '@' are only valid between the enclosing
global labels (or inside the current macro).
Two other possibilities for label names are "all-characters-are-minus"
(then it is an anonymous backward label) and "all-characters-are-plus"
(then it is an anonymous forward label).

Every command is one of the following:
    An assembler mnemonic with an optional argument
    A pseudo opcode, beginning with a "!" character
    An explicit symbol definition (SYMBOL = VALUE)
    A pc definition, beginning with a "*" character
    A macro call, beginning with a "+" character
...and the syntax of those things varies. :)

Assembler mnemonics and pseudo opcodes are case insensitive, so
whether you write "LDA" or "lda" or "LdA" does not make a difference.

In earlier releases of ACME, arithmetic operators like MOD, XOR, LSL
had to be written in UPPER CASE. This is no longer needed.

Symbol names are case sensitive, so "label" and "Label" are two
different things.
