mirror of
https://github.com/badvision/lawless-legends.git
synced 2025-03-01 03:30:04 +00:00
359 lines
14 KiB
Plaintext
359 lines
14 KiB
Plaintext
|
|
|
|
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
|
|
|
|
basout = $ffd2 ; explicit global label def.
|
|
; 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".
|
|
basout = $ffd2 ; explicit global label def.
|
|
; Now "basout" is defined as a global label having the value $ffd2.
|
|
; 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 label, 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 label, 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 label (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 labels:
|
|
|
|
There are global labels (their names starting with a letter or an
|
|
underscore character). These can be accessed throughout the whole
|
|
assembly.
|
|
Then there are local labels (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").
|
|
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 LABEL=VALUE).
|
|
|
|
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 / !sl
|
|
...for defining the scope of local labels and saving global labels.
|
|
|
|
!convtab / !pet / !raw / !scr / !scrxor / !text
|
|
...for converting and outputting strings.
|
|
|
|
!do / !endoffile / !for / !if / !ifdef / !set
|
|
...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.
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
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 select output format ("plain" or "cbm")
|
|
-o, --outfile FILE select output file.
|
|
Output filename 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".
|
|
|
|
-l, --labeldump FILE select label dump file.
|
|
This can also be given using the "!sl" pseudo opcode.
|
|
|
|
--cpu CPU_TYPE set processor type.
|
|
This can be changed in the source code using the "!cpu" pseudo
|
|
opcode. Defaults to 6502.
|
|
|
|
--setpc NUMBER set program counter.
|
|
This can also be given in the source code using "*=NUMBER".
|
|
|
|
--initmem NUMBER 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 the
|
|
"!source" pseudo opcode. If not given, defaults to 64.
|
|
|
|
-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.
|
|
|
|
-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 maths parser
|
|
----------------------------------------------------------------------
|
|
|
|
ACME has a relatively powerful maths parser. This parser is used
|
|
whenever ACME expects to read an integer 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.
|
|
All calculations are done using signed 32-bit integer arithmetic and
|
|
all label values are internally handled using 32 bits.
|
|
|
|
|
|
This is a list of the operators currently known by ACME:
|
|
|
|
Priority Example Meaning Alias
|
|
------------------------------------------------------------
|
|
13 ! v Complement of NOT
|
|
12 v ^ w To the power of
|
|
11 - v Negate
|
|
10 v * w Multiply
|
|
10 v / w Integer-Divide DIV
|
|
10 v % w Remainder of DIV MOD
|
|
9 v + w Add
|
|
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 Lowbyte of
|
|
7 > v Highbyte of
|
|
7 ^ v Bankbyte 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 <>, ><
|
|
4 v = w Equal
|
|
3 v & w Bit-wise AND AND
|
|
2 Bit-wise exclusive OR EOR, XOR
|
|
1 v | w Bit-wise OR OR
|
|
|
|
Operations with higher priority are done first. Of course you can
|
|
change this using parentheses. If you prefer the aliases over the
|
|
shorthand characters, note that they must be written in capital
|
|
letters.
|
|
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.
|
|
|
|
|
|
This is a list of the value formats currently known by ACME:
|
|
|
|
Example Meaning Prefix
|
|
---------------------------------------------------------------------
|
|
GetByte Global label None
|
|
.Loop Local label "."
|
|
9260 Decimal value None
|
|
$1a8e Hexadecimal value "$"
|
|
0x8b4f Hexadecimal value "0x"
|
|
&1054 Octal value "&"
|
|
%10010 Binary value "%"
|
|
In binary values you can substitute the characters "0" and "1" by "."
|
|
and "#" respectively. This way the values are much more readable.
|
|
"r" Character value Double quotes
|
|
'r' Character value Single quotes
|
|
The value depends on the current conversion table, chosen using the
|
|
"!ct" pseudo opcode.
|
|
* The current PC "*"
|
|
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. 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, entirely useless 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.
|
|
|
|
Every statement consists of an optional "implicit label definition"
|
|
and an optional "command". These are separated from each other using
|
|
any number of SPACE or TAB characters. If an implicit label definition
|
|
has blanks before it, a warning is given (to spot typing errors - see
|
|
Errors.txt for more info).
|
|
|
|
Every label 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 a dot ("."), making the label a local one. Two other possibilities
|
|
for label names are "all-characters-are-minus" (then it's an anonymous
|
|
backward label) and "all-characters-are-plus" (then it's an anonymous
|
|
forward label).
|
|
|
|
Every command is one of the following:
|
|
An assembler opcode
|
|
A pseudo opcode, beginning with a "!" character
|
|
An explicit label definition (label=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.
|
|
|
|
Arithmetic operators like MOD, XOR, LSL must be written in UPPER CASE;
|
|
this rule simply serves to make them stand out.
|
|
|
|
Label names are case sensitive, so "label" and "Label" are two
|
|
different things.
|