64tass v1.53 r1515 reference manual
64tass v1.53 r1515 reference manual
This is the manual for 64tass, the multi pass optimizing macro assembler for the 65xx series
of processors. Key features:
Open source portable C with minimal dependencies
Familiar syntax to Omicron TASS and TASM
Supports 6502, 65C02, R65C02, W65C02, 65CE02, 65816, DTV, 65EL02, 4510
Arbitrary-precision integers and bit strings, double precision floating point numbers
Character and byte strings, array arithmetic
Handles UTF-8, UTF-16 and 8 bit RAW encoded source files, Unicode character strings
Supports Unicode identifiers with compatibility normalization and optional case insen‐
sitivity
Built-in “linker” with section support
Various memory models, binary targets and text output formats (also Hex/S-record)
Assembly and label listings available for debugging or exporting
Conditional compilation, macros, structures, unions, scopes
Contrary how the length of this document suggests 64tass can be used with just basic 6502
assembly knowledge in simple ways like any other assembler. If some advanced functionality
is needed then this document can serve as a reference.
This is a development version. Features or syntax may change as a result of cor‐
rections in non-backwards compatible ways in some rare cases. It's difficult to get
everything “right” first time.
Project page: http://sourceforge.net/projects/tass64/
The page hosts the latest and older versions with sources and a bug and a feature request
tracker.
1
Table of Contents
1 Table of Contents
2 Usage tips
3 Expressions and data types
3.1 Integer constants
3.2 Bit string constants
3.3 Floating point constants
3.4 Character string constants
3.5 Byte string constants
3.6 Lists and tuples
3.7 Dictionaries
3.8 Code
3.9 Addressing modes
3.10 Uninitialized memory
3.11 Booleans
3.12 Types
3.13 Symbols
3.13.1 Regular symbols
3.13.1 Local symbols
3.13.1 Anonymous symbols
3.13.1 Constant and re-definable symbols
3.13.1 The star label
3.14 Built-in functions
3.14.1 Mathematical functions
3.14.1 Other functions
3.15 Expressions
1 / 68
64tass v1.53 r1515 reference manual
3.15.1
3.15.1
3.15.1
3.15.1
3.15.1
3.15.1
3.15.1
Operators
Comparison operators
Bit string extraction operators
Conditional operators
Address length forcing
Compound assignment
Slicing and indexing
4 Compiler directives
4.1 Controlling the compile offset and program counter
4.2 Dumping data
4.2.1 Storing numeric values
4.2.1 Storing string values
4.3 Text encoding
4.4 Structured data
4.4.1 Structure
4.4.1 Union
4.4.1 Combined use of structures and unions
4.5 Macros
4.5.1 Parameter references
4.5.1 Text references
4.6 Custom functions
4.7 Conditional assembly
4.7.1 If, else if, else
4.7.1 Switch, case, default
4.8 Repetitions
4.9 Including files
4.10 Scopes
4.11 Sections
4.12 65816 related
4.13 Controlling errors
4.14 Target
4.15 Misc
4.16 Printer control
5 Pseudo instructions
5.1 Aliases
5.2 Always taken branches
5.3 Long branches
6 Original turbo assembler compatibility
6.1 How to convert source code for use with 64tass
6.2 Differences to the original turbo ass macro on the C64
6.3 Labels
6.4 Expression evaluation
6.5 Macros
6.6 Bugs
7 Command line options
7.1 Output options
7.2 Operation options
7.3 Diagnostic options
7.4 Target selection on command line
7.5 Symbol listing
7.6 Assembly listing
7.7 Other options
8 Messages
8.1 Warnings
8.2 Errors
8.3 Fatal errors
2 / 68
64tass v1.53 r1515 reference manual
9 Credits
10 Default translation and escape sequences
10.1 Raw 8-bit source
10.1.1 The none encoding for raw 8-bit
10.1.1 The screen encoding for raw 8-bit
10.2 Unicode and ASCII source
10.2.1 The none encoding for Unicode
10.2.1 The screen encoding for Unicode
11 Opcodes
11.1 Standard 6502 opcodes
11.2 6502 illegal opcodes
11.3 65DTV02 opcodes
11.4 Standard 65C02 opcodes
11.5 R65C02 opcodes
11.6 W65C02 opcodes
11.7 W65816 opcodes
11.8 65EL02 opcodes
11.9 65CE02 opcodes
11.10 CSG 4510 opcodes
12 Appendix
12.1 Assembler directives
12.2 Built-in functions
12.3 Built-in types
2
Usage tips
64tass is a command line assembler, the source can be written in any text editor. As a mini‐
mum the source filename must be given on the command line. The “-a” command line option
is highly recommended if the source is Unicode or ASCII.
64tass -a src.asm
There are also some useful parameters which are described later.
For comfortable compiling I use such “Makefile”s (for make):
demo.prg: source.asm macros.asm pic.drp music.bin
64tass -C -a -B -i source.asm -o demo.tmp
pucrunch -ffast -x 2048 demo.tmp >demo.prg
This way “demo.prg” is recreated by compiling “source.asm” whenever “source.asm”,
“macros.asm”, “pic.drp” or “music.bin” had changed.
Of course it's not much harder to create something similar for win32 (make.bat), however
this will always compile and compress:
64tass.exe -C -a -B -i source.asm -o demo.tmp
pucrunch.exe -ffast -x 2048 demo.tmp >demo.prg
Here's a slightly more advanced Makefile example with default action as testing in VICE,
clean target for removal of temporary files and compressing using an intermediate tempo‐
rary file:
all: demo.prg
x64 -autostartprgmode 1 -autostart-warp +truedrive +cart $<
demo.prg: demo.tmp
pucrunch -ffast -x 2048 $< >$@
3 / 68
64tass v1.53 r1515 reference manual
demo.tmp: source.asm macros.asm pic.drp music.bin
64tass -C -a -B -i $< -o $@
.INTERMEDIATE: demo.tmp
.PHONY: all clean
clean:
$(RM) demo.prg demo.tmp
It's useful to add a basic header to your source files like the one below, so that the resulting
file is directly runnable without additional compression:
*
+
= $0801
.word (+), 2005 ;pointer, line number
.null $9e, format("%d", start);will be sys 4096
.word 0
;basic line end
*
= $1000
start
rts
A frequently coming up question is, how to automatically allocate memory, without hacks
like ∗=∗+1? Sure there's .byte and friends for variables with initial values but what about zero
page, or RAM outside of program area? The solution is to not use an initial value by using “?”
or not giving a fill byte value to .fill.
*
p1
temp
= $02
.word ?
.fill 10
;a zero page pointer
;a 10 byte temporary area
Space allocated this way is not saved in the output as there's no data to save at those ad‐
dresses.
What about some code running on zero page for speed? It needs to be relocated, and the
length must be known to copy it there. Here's an example:
ldx #size(zpcode)-1;calculate length
lda zpcode,x
sta wrbyte,x
dex
;install to zero page
bpl jsr wrbyte
rts
;code continues here but is compiled to run from $02
zpcode .logical $02
wrbyte sta $ffff
;quick byte writer at $02
inc wrbyte+1
bne +
inc wrbyte+2
+
rts
.here
-
The assembler supports lists and tuples, which does not seems interesting at first as it sound
like something which is only useful when heavy scripting is involved. But as normal arith‐
metic operations also apply on all their elements at once, this could spare quite some typing
and repetition.
Let's take a simple example of a low/high byte jump table of return addresses, this usually
involves some unnecessary copy/pasting to create a pair of tables with constructs like
4 / 68
64tass v1.53 r1515 reference manual
>(label−1).
jumpcmd lda hibytes,x
; selected routine in X register
pha
lda lobytes,x
; push address to stack
pha
rts
; jump, rts will increase pc by one!
; Build an anonymous list of jump addresses minus 1
= (cmd_p, cmd_c, cmd_m, cmd_s, cmd_r, cmd_l, cmd_e)-1
lobytes .byte <(-)
; low bytes of jump addresses
hibytes .byte >(-)
; high bytes
There are some other tips below in the descriptions.
3
Expressions and data types
3.1
Integer constants
Integer constants can be entered as decimal digits of arbitrary length. An underscore can be
used between digits as a separator for better readability of long numbers. The following op‐
erations are accepted:
x + y
x − y
x ∗ y
x / y
x % y
x ∗∗ y
−x
+x
~x
x | y
x ^ y
x & y
x << y
x >> y
add x to y
subtract y from x
multiply x with y
integer divide x by y
integer modulo of x divided by y
x raised to power of y
negated value
unchanged
−x − 1
bitwise or
bitwise xor
bitwise and
logical shift left
arithmetic shift right
Table 1: Integer operators and functions
2 + 2 is 4
4 − 1 is 3
2 ∗ 3 is 6
7 / 2 is 3
5 % 2 is 1
2 ∗∗ 4 is 16
−2 is −2
+2 is 2
~3 is −4
2 | 6 is 6
2 ^ 6 is 4
2 & 6 is 2
1 << 3 is 8
−8 >> 3 is −1
Integers are automatically promoted to float as necessary in expressions. Other types can be
converted to integer using the integer type int.
.byte 23
; decimal
lda #((bitmap >> 10) & $0f) | ((screen >> 6) & $f0)
sta $d018
3.2
Bit string constants
Bit string constants can be entered in hexadecimal form with a leading dollar sign or in bi‐
nary with a leading percent sign. An underscore can be used between digits as a separator
for better readability of long numbers. The following operations are accepted:
~x
y .. x
y x n
~%101 is ~%101
invert bits
$a .. $b is $ab
concatenate bits
%101 x 3 is %101101101
repeat
Table 2: Bit string operators and functions
5 / 68
64tass v1.53 r1515 reference manual
$a[1] is %1
$1234[4:8] is $3
~$2 | $6 is ~$0
~$2 ^ $6 is ~$4
~$2 & $6 is $4
$0f << 4 is $0f0
~$f4 >> 4 is ~$f
extract bit(s)
slice bits
bitwise or
bitwise xor
bitwise and
bitwise shift left
bitwise shift right
x[n]
x[s]
x | y
x ^ y
x & y
x << y
x >> y
Length of bit string constants are defined in bits and is calculated from the number of bit
digits used including leading zeros.
Bit strings are automatically promoted to integer or floating point as necessary in expres‐
sions. The higher bits are extended with zeros or ones as needed.
Bit strings support indexing and slicing. This is explained in detail in section “Slicing and
indexing”.
Other types can be converted to bit string using the bit string type bits.
.byte $33
; hex
.byte %00011111 ; binary
.text $1234
; $34, $12
lda
and
ora
sta
$01
#~$07
#$05
$01
lda $d015
and #~%00100000 ;clear a bit
sta $d015
3.3
Floating point constants
Floating point constants have a radix point in them and optionally an exponent. A decimal
exponent is “e” while a binary one is “p”. An underscore can be used between digits as a
separator for better readability. The following operations can be used:
x + y
x − y
x ∗ y
x / y
x % y
x ∗∗ y
−x
+x
x | y
x ^ y
x & y
x << y
x >> y
~x
2.2 + 2.2 is 4.4
add x to y
4.1 − 1.1 is 3.0
subtract y from x
1.5 ∗ 3 is 4.5
multiply x with y
7.0 / 2.0 is 3.5
integer divide x by y
5.0 % 2.0 is 1.0
integer modulo of x divided by y
2.0 ∗∗ −1 is 0.5
x raised t power of y
−2.0 is −2.0
negated value
+2.0 is 2.0
unchanged
2.5 | 6.5 is 6.5
bitwise or
2.5 ^ 6.5 is 4.0
bitwise xor
2.5 & 6.5 is 2.5
bitwise and
1.0 << 3.0 is 8.0
logical shift left
−8.0 >> 4 is −0.5
arithmetic shift right
~2.1 is almost −2.1
almost −x
Table 3: Floating point operators and functions
As usual comparing floating point numbers for (non) equality is a bad idea due to rounding
errors.
The only predefined constant is pi.
6 / 68
64tass v1.53 r1515 reference manual
Floating point numbers are automatically truncated to integer as necessary. Other types
can be converted to floating point by using the type float.
Fixed point conversion can be done by using the shift operators. For example a 8.16 fixed
point number can be calculated as (3.14 << 16) & $ffffff. The binary operators operate like
if the floating point number would be a fixed point one. This is the reason for the strange
definition of inversion.
.byte 3.66e1
.byte $1.8p4
.sint 12.2p8
3.4
; 36.6, truncated to 36
; 4:4 fixed point number (1.5)
; 8:8 fixed point number (12.2)
Character string constants
Character strings are enclosed in single or double quotes and can hold any Unicode charac‐
ter. Operations like indexing or slicing are always done on the original representation. The
current encoding is only applied when it's used in expressions as numeric constants or in
context of text data directives. Doubling the quotes inside string literals escapes them and
results in a single quote.
"a" .. "b" is "ab"
concatenate strings
"b" in "abc" is true
is substring of
"ab" x 3 is "ababab"
repeat
"abc"[1] is "b"
character from start
"abc"[−1] is "c"
character from end
"abc"[:] is "abc"
no change
"abc"[1:] is "bc"
cut off start
"abc"[:−1] is "ab"
cut off end
"abc"[::−1] is "cba"
reverse
Table 4: Character string operators and functions
y .. x
y in x
a x n
a[i]
a[i]
a[s]
a[s]
a[s]
a[s]
Character strings are converted to integers, byte and bit strings as necessary using the cur‐
rent encoding and escape rules. For example when using a sane encoding "z"−"a" is 25.
Other types can be converted to character strings by using the type str or by using the
repr and format functions.
Character strings support indexing and slicing. This is explained in detail in section “Slic‐
ing and indexing”.
mystr
= "oeU"
.text 'it''s'
.word "ab"+1
.text
.text
.text
.text
3.5
; text
; text: it's
; character, results in "bb" usually
"text"[:2]
;
"text"[2:]
;
"text"[:-1]
;
"reverse"[::-1];
"te"
"xt"
"tex"
"esrever"
Byte string constants
Byte strings are like character strings, but hold bytes instead of characters.
Quoted character strings prefixing by “b”, “l”, “n”, “p” or “s” characters can be used to
create byte strings. The resulting byte string contains what .text, .shiftl, .null, .ptext and
.shift would create.
y .. x
b"a" .. b"b" is b"ab"
concatenate strings
Table 5: Byte string operators and functions
7 / 68
64tass v1.53 r1515 reference manual
b"b" in b"abc" is true
b"ab" x 3 is b"ababab"
b"abc"[1] is b"b"
b"abc"[−1] is b"c"
b"abc"[:] is b"abc"
b"abc"[1:] is b"bc"
b"abc"[:−1] is b"ab"
b"abc"[::−1] is b"cba"
is substring of
repeat
byte from start
byte from end
no change
cut off start
cut off end
reverse
y in x
a x n
a[i]
a[i]
a[s]
a[s]
a[s]
a[s]
Byte strings support indexing and slicing. This is explained in detail in section “Slicing and
indexing”.
Other types can be converted to byte strings by using the type bytes.
mystr
3.6
.enc "screen"
= b"oeU"
.enc "none"
;use screen encoding
;convert text to bytes, like .text
;normal encoding
.text
.text
.text
.text
.text
;text as
;convert
;convert
;convert
;convert
mystr
s"p1"
l"p2"
n"p3"
p"p4"
originally encoded
to bytes like .shift
to bytes like .shiftl
to bytes like .null
to bytes like .ptext
Lists and tuples
Lists and tuples can hold a collection of values. Lists are defined from values separated by
comma between square brackets [1, 2, 3], an empty list is []. Tuples are similar but are en‐
closed in parentheses instead. An empty tuple is (), a single element tuple is (4,) to differen‐
tiate from normal numeric expression parentheses. When nested they function similar to an
array. Currently both types are immutable.
y .. x
y in x
a x n
a[i]
a[i]
a[s]
a[s]
a[s]
a[s]
∗a
[1] .. [2] is [1, 2]
concatenate lists
2 in [1, 2, 3] is true
is member of list
[1, 2] x 2 is [1, 2, 1, 2]
repeat
("1", 2)[1] is 2
element from start
("1", 2, 3)[−1] is 3
element from end
(1, 2, 3)[:] is (1, 2, 3)
no change
(1, 2, 3)[1:] is (2, 3)
cut off start
(1, 2.0, 3)[:−1] is (1, 2.0)
cut off end
(1, 2, 3)[::−1] is (3, 2, 1)
reverse
format("%d: %s", ∗mylist)
convert to arguments
Table 6: List and tuple operators and functions
Arithmetic operations are applied on the all elements recursively, therefore [1, 2] + 1 is [2,
3], and abs([1, −1]) is [1, 1].
Arithmetic operations between lists are applied one by one on their elements, so [1, 2] +
[3, 4] is [4, 6].
When lists form an array and columns/rows are missing the smaller array is stretched to
fill in the gaps if possible, so [[1], [2]] ∗ [3, 4] is [[3, 4], [6, 8]].
Lists and tuples support indexing and slicing. This is explained in detail in section “Slic‐
ing and indexing”.
mylist = [1, 2, "whatever"]
mytuple = (cmd_e, cmd_g)
8 / 68
64tass v1.53 r1515 reference manual
mylist
keys
call_l
call_h
= ("e", cmd_e, "g", cmd_g, "i", cmd_i)
.text mylist[::2]
; keys ("e", "g", "i")
.byte mylist[1::2]-1; routines (>cmd_e−1, >cmd_g−1, >cmd_i−1)
The range(start, end, step) built-in function can be used to create lists of integers in a range
with a given step value. At least the end must be given, the start defaults to 0 and the step to
1. Sounds not very useful, so here are a few examples:
;Bitmask table, 8 bits from left to right
.byte %10000000 >> range(8)
;Classic 256 byte single period sinus table with values of 0−255.
.byte 128.5 + 127 * sin(range(256) * rad(360.0/256))
;Screen row address tables
= $400 + range(0, 1000, 40)
scrlo
.byte <(-)
scrhi
.byte >(-)
3.7
Dictionaries
Dictionaries are unsorted lists holding key and value pairs. Definition is done by collecting
key:value pairs separated by comma between braces {1:"value", "key":1, :"optional default
value"}.
Looking up a non existing key is normally an error unless a default value is given. An
empty dictionary is {}. Currently this type is immutable. Numeric and string keys are ac‐
cepted, the value can be anything.
{"1":2}["1"] is 2
value lookup
1 in {1:2} is true
is a key
Table 7: Dictionary operators and functions
x[i]
y in x
; Simple lookup
.text {1:"one", 2:"two"}[2]; "two"
; 16 element "fader" table 1->15->12->11->0
.byte {1:15, 15:12, 12:11, :0}[range(16)]
3.8
Code
Code holds the result of compilation in binary and other enclosed objects. In an arithmetic
operation it's used as the numeric address of the memory where it starts. The compiled con‐
tent remains static even if later parts of the source overwrite the same memory area.
Indexing and slicing of code to access the compiled content might be imple‐
mented differently in future releases. Use this feature at your own risk for now, you
might need to update your code later.
a.b
a[i]
a[i]
a[s]
a[s]
a[s]
a[s]
mydata
mycode
label.locallabel
member
label[1]
element from start
label[−1]
element from end
label[:]
copy as tuple
label[1:]
cut off start, as tuple
label[:−1]
cut off end, as tuple
label[::−1]
reverse, as tuple
Table 8: Label operators and functions
.word 1, 4, 3
.block
9 / 68
64tass v1.53 r1515 reference manual
local
lda #0
.bend
ldx
ldx
ldx
ldx
jmp
3.9
#size(mydata)
#len(mydata)
#mycode[0]
#mydata[1]
mycode.local
;6 bytes (3∗2)
;3 elements
;lda instruction, $a9
;2nd element, 4
;address of local label
Addressing modes
Addressing modes are used for determining addressing modes of instructions.
For indexing there must be no white space between the comma and the register letter,
otherwise the indexing operator is not recognized. On the other hand put a space between
the comma and a single letter symbol in a list to avoid it being recognized as an operator.
#
#+
#−
(
[
,b
,d
,k
,r
,s
,x
,y
,z
immediate
signed immediate
signed immediate
indirect
long indirect
data bank indexed
direct page indexed
program bank indexed
data stack pointer indexed
stack pointer indexed
x register indexed
y register indexed
z register indexed
Table 9: Addressing mode operators
Parentheses are used for indirection and square brackets for long indirection. These opera‐
tions are only available after instructions and functions to not interfere with their normal use
in expressions.
Several addressing mode operators can be combined together. Currently the complex‐
ity is limited to 4 operators. This is enough to describe all addressing modes of the
supported CPUs.
#
#+
#−
#addr,#addr
addr
addr,addr
addr,addr,addr
(addr)
(addr),y
(addr),z
(addr,x)
[addr]
[addr],y
#addr,b
#addr,b,x
#addr,b,y
immediate
signed immediate
signed immediate
move
direct or relative
direct page bit
direct page bit relative jump
indirect
indirect y indexed
indirect z indexed
x indexed indirect
long indirect
long indirect y indexed
data bank indexed
data bank x indexed
data bank y indexed
Table 10: Valid addressing mode operator
10 / 68
lda #$12
lda #+127
lda #−128
mvp #5,#6
lda $12 lda $1234 bne $1234
rmb 5,$12
bbs 5,$12,$1234
lda ($12) jmp ($1234)
lda ($12),y
lda ($12),z
lda ($12,x) jmp ($1234,x)
lda [$12] jmp [$1234]
lda [$12],y
lda #0,b
lda #0,b,x
lda #0,b,y
combinations
64tass v1.53 r1515 reference manual
#addr,d
#addr,d,x
#addr,d,y
(#addr,d)
(#addr,d,x)
(#addr,d),y
(#addr,d),z
[#addr,d]
[#addr,d],y
#addr,k
(#addr,k,x)
#addr,r
(#addr,r),y
#addr,s
(#addr,s),y
addr,x
addr,y
direct page indexed
direct page x indexed
direct page y indexed
direct page indirect
direct page x indexed indirect
direct page indirect y indexed
direct page indirect z indexed
direct page long indirect
direct page long indirect y indexed
program bank indexed
program bank x indexed indirect
data stack indexed
data stack indexed indirect y indexed
stack indexed
stack indexed indirect y indexed
x indexed
y indexed
lda
lda
ldx
lda
lda
lda
lda
lda
lda
jsr
jmp
lda
lda
lda
lda
lda
lda
#0,d
#0,d,x
#0,d,y
(#$12,d)
(#$12,d,x)
(#$12,d),y
(#$12,d),z
[#$12,d]
[#$12,d],y
#0,k
(#$1234,k,x)
#1,r
#($12,r),y
#1,s
(#$12,s),y
$12,x
$12,y
Direct page, data bank, program bank indexed and long addressing modes of instructions
are intelligently chosen based on the instruction type, the address ranges set up by .dpage,
.databank and the current program counter address. Therefore the “,d”, “,b” and “,k” index‐
ing is only used in very special cases.
The immediate direct page indexed “#0,d” addressing mode is usable for direct page ac‐
cess. The 8 bit constant is a direct offset from the start of actual direct page.
The immediate data bank indexed “#0,b” addressing mode is usable for data bank access.
The 16 bit constant is a direct offset from the start of actual data bank.
The immediate program bank indexed “#0,k” addressing mode is usable for program bank
jumps, braches and calls. The 16 bit constant is a direct offset from the start of actual pro‐
gram bank.
The immediate stack indexed “#0,s” and data stack indexed “#0,r” accept 8 bit constants
as an offset from the start of (data) stack. These are sometimes written without the immedi‐
ate notation, but this makes it more clear what's going on. For the same reason the move in‐
structions are written with an immediate addressing mode “#0,#0” as well.
The immediate (#) addressing mode expects unsigned values of byte or word size. There‐
fore it only accepts constants of 1 byte or in range 0–255 or 2 bytes or in range 0–65535.
The signed immediate (#+ and #−) addressing mode is to allow signed numbers to be used
as immediate constants. It accepts a single byte or an integer in range −128–127, or two
bytes or an integer of −32768–32767.
The use of signed immediate (like #−3) is seamless, but it needs to be explicitly written out
for variables or expressions (#+variable). In case the unsigned variant is needed but the ex‐
pression starts with a negation then it needs to be put into parentheses (#(-variable)) or else
it'll change the address mode to signed.
Normally addressing mode operators are used in expressions right after instructions.
They can also be used for defining stack variable symbols when using a 65816, or to force a
specific addressing mode.
param
const
= #1,s
= #1
lda #0,b
lda param
lda param+1
lda (param),y
ldx const
;define a stack variable
;immediate constant
;always "absolute" lda $0000
;results in lda #$01,s
;results in lda #$02,s
;results in lda (#$01,s),y
;results in ldx #$01
11 / 68
64tass v1.53 r1515 reference manual
lda #-2
3.10
;negative constant, $fe
Uninitialized memory
There's a special value for uninitialized memory, it's represented by a question mark. When‐
ever it's used to generate data it creates a “hole” where the previous content of memory is
visible.
Uninitialized memory holes without previous content are not saved unless it's really nec‐
essary for the output format, in that case it's replaced with zeros.
It's not just data generation statements (e.g. .byte) that can create uninitialized memory,
but .fill, .align, .offs or address manipulation as well.
*
= $200
.word ?
.fill 10
.align 64
.offs 16
3.11
Booleans
;bytes as necessary
;2 bytes
;10 bytes
;bytes as necessary
;16 bytes
There are two predefined boolean constant variables, true and false.
Booleans are created by comparison operators (<, <=, !=, ==, >=, >), logical operators (&&, ||,
^^, !), the membership operator (in) and the all and any functions.
Normally in numeric expressions true is 1 and false is 0, unless the “-Wstrict-bool” com‐
mand line option was used.
Other types can be converted to boolean by using the type bool.
bits
bool
bytes
code
float
int
str
3.12
At least one non-zero bit
When true
At least one non-zero byte
Address is non-zero
Not 0.0
Not zero
At least one non-zero byte after translation
Table 11: Boolean values of various types
Types
The various types mentioned earlier have predefined names. These can used for conversions
or type checks.
address
bits
bool
bytes
code
dict
float
gap
int
list
str
tuple
Address type
Bit string type
Boolean type
Byte string type
Code type
Dictionary type
Floating point type
Uninitialized memory type
Integer type
List type
Character string type
Tuple type
Table 12: Built-in type names
12 / 68
64tass v1.53 r1515 reference manual
Type type
type
.cerror type(var) != str, "Not a string!"
.text str(year)
; convert to string
3.13
Symbols
Symbols are used to reference objects. Regularly named, anonymous and local symbols are
supported. These can be constant or re-definable.
Scopes are where symbols are stored and looked up. The global scope is always defined
and it can contain any number of nested scopes.
Symbols must be uniquely named in a scope, therefore in big programs it's hard to come
up with useful and easy to type names. That's why local and anonymous symbols exists. And
grouping certain related symbols into a scope makes sense sometimes too.
Scopes are usually created by .proc and .block directives, but there are a few other ways.
Symbols in a scope can be accessed by using the dot operator, which is applied between the
name of the scope and the symbol (e.g. myconsts.math.pi).
3.13.1 Regular symbols
Regular symbol names are starting with a letter and containing letters, numbers and under‐
scores. Unicode letters are allowed if the “-a” command line option was used. There's no re‐
striction on the length of symbol names.
Care must be taken to not use duplicate names in the same scope when the symbol is
used as a constant. Case sensitivity can be enabled with the “-C” command line option, other‐
wise all symbols are matched case insensitive.
Duplicate names in parent scopes are never a problem, they'll just be “shadowed”. This
could be either good by reducing collisions and gives the ability to override “defaults” de‐
fined in lower scopes. On the other hand it's possible to mix-up the new symbol with a old
one by mistake, which is hard to notice.
A regular symbol is looked up first in the current scope, then in lower scopes until the
global scope is reached.
f
g
n
f.x
.block
.block
nop
.bend
.bend
;jump here
jsr f.g.n
= 3
;reference from a scope
;create x in scope f with value 3
3.13.2 Local symbols
Local symbols have their own scope between two regularly named code symbols and are as‐
signed to the code symbol above them.
Therefore they're easy to reuse without explicit scope declaration directives.
Not all regularly named symbols can be scope boundaries just plain code symbol ones
without anything or an opcode after them (no macros!). Symbols defined as procedures,
blocks, macros, functions, structures and unions are ignored. Also symbols defined by .var,
:= or = don't apply, and there are a few more exceptions, so stick to using plain code labels.
The name must start with an underscore (_), otherwise the same character restrictions
apply as for regular symbols. There's no restriction on the length of the name.
13 / 68
64tass v1.53 r1515 reference manual
Care must be taken to not use the duplicate names in the same scope when the symbol is
used as a constant.
A local symbol is only looked up in it's own scope and nowhere else.
incr
_skip
decr
_skip
inc ac
bne _skip
inc ac+1
rts
lda
bne
dec
dec
jmp
ac
_skip
ac+1
ac
incr._skip
;symbol reused here
;this works too, but is not advised
3.13.3 Anonymous symbols
Anonymous symbols don't have a unique name and are always called as a single plus or mi‐
nus sign. They are also called as forward (+) and backward (−) references.
When referencing them “−” means the first backward, “−−” means the second backwards
and so on. It's the same for forward, but with “+”. In expressions it may be necessary to put
them into brackets.
-
+
ldy
ldx
txa
cmp
bcc
adc
sta
inx
bne
dey
bne
#4
#0
#3
+
#44
$400,x
--
Excessive nesting or long distance references create poorly readable code. It's also very easy
to copy-paste a few lines of code with these references into a code fragment already contain‐
ing similar references. The result is usually a long debugging session to find out what went
wrong.
These references are also useful in segments, but this can create a nice trap when seg‐
ments are copied into the code with their internal references.
+
bne +
#somemakro
nop
;let's hope that this segment does
;not contain forward references...
A anonymous symbols are looked up first in the current scope, then in lower scopes until the
global scope is reached.
3.13.4 Constant and re-definable symbols
Constant symbols can be created with the equal sign. These are not re-definable. Forward
referencing of them is allowed as they retain the objects over compilation passes.
Symbols in front of code or certain assembler directives are created as constant symbols
too. They are bound to the object following them.
Re-definable symbols can be created by the .var directive or := construct. These are also
14 / 68
64tass v1.53 r1515 reference manual
called as variables as they don't carry their content over from the previous pass. Therefore
it's not possible to use them before their definition.
border
= $d020
inc border
variabl .var 1
var2
:= 1
.rept 10
.byte variabl
variabl .var variabl+1
.next
;a constant
;inc $d020
;a variable
;another variable
;increment it
3.13.5 The star label
The “∗” symbol denotes the current program counter value. When accessed it's value is the
program counter at the beginning of the line. Assigning to it changes the program counter
and the compiling offset.
3.14
Built-in functions
Built-in functions are pre-assigned to the symbols listed below. If you reuse these symbols in
a scope for other purposes then they become inaccessible, or can perform a different func‐
tion.
Built-in functions can be assigned to symbols (e.g. sinus = sin), and the new name can be
used as the original function. They can even be passed as parameters to functions.
3.14.1 Mathematical functions
floor()
Round down. E.g. floor(−4.8) is −5.0
round()
Round to nearest away from zero. E.g. round(4.8) is 5.0
ceil()
Round up. E.g. ceil(1.1) is 2.0
trunc()
Round down towards zero. E.g. trunc(−1.9) is −1
frac()
Fractional part. E.g. frac(1.1) is 0.1
sqrt()
Square root. E.g. sqrt(16.0) is 4.0
cbrt()
Cube root. E.g. cbrt(27.0) is 3.0
log10()
Common logarithm. E.g. log10(100.0) is 2.0
log()
Natural logarithm. E.g. log(1) is 0.0
exp()
Exponential. E.g. exp(0) is 1.0
pow(, )
A raised to power of B. E.g. pow(2.0, 3.0) is 8.0
sin()
Sine. E.g. sin(0.0) is 0.0
15 / 68
64tass v1.53 r1515 reference manual
asin()
Arc sine. E.g. asin(0.0) is 0.0
sinh()
Hyperbolic sine. E.g. sinh(0.0) is 0.0
cos()
Cosine. E.g. cos(0.0) is 1.0
acos()
Arc cosine. E.g. acos(1.0) is 0.0
cosh()
Hyperbolic cosine. E.g. cosh(0.0) is 1.0
tan()
Tangent. E.g. tan(0.0) is 0.0
atan()
Arc tangent. E.g. atan(0.0) is 0.0
tanh()
Hyperbolic tangent. E.g. tanh(0.0) is 0.0
rad()
Degrees to radian. E.g. rad(0.0) is 0.0
deg()
Radian to degrees. E.g. deg(0.0) is 0.0
hypot(, )
Polar distance. E.g. hypot(4.0, 3.0) is 5.0
atan2(, )
Polar angle in −pi to +pi range. E.g. atan2(0.0, 3.0) is 0.0
abs()
Absolute value. E.g. abs(−1) is 1
sign()
Returns the sign of value as −1, 0 or 1 for negative, zero and positive. E.g. sign(−5) is
−1
3.14.2 Other functions
all()
Return truth for various definitions of “all”.
all
all
all
all
all($f) is true
bits set or no bits at all
all("c") is true
characters non-zero or empty string
all(b"c") is true
bytes non-zero or no bytes
all([true, true, false]) is false
elements true or empty list
Table 13: All function
Only booleans in a list are accepted with the “-Wstrict-bool” command line option.
any()
Return truth for various definitions of “any”.
at
at
at
at
least
least
least
least
one
one
one
one
any(~$f) is false
bit set
any("c") is true
non-zero character
any(b"c") is true
non-zero byte
any([true, true, false]) is true
true element
Table 14: Any function
Only booleans in a list are accepted with the “-Wstrict-bool” command line option.
16 / 68
64tass v1.53 r1515 reference manual
format([, , …])
Create string from values according to a format string.
The format function converts a list of values into a character string. The converted val‐
ues are inserted in place of the % sign. Optional conversion flags and minimum field
length may follow, before the conversion type character. These flags can be used:
alternate form ($a, %10, 10.)
width/precision from list
precision
pad with zeros
left adjusted (default right)
blank when positive or minus sign
sign even if positive
Table 15: Formatting flags
#
∗
.
0
−
+
The following conversion types are implemented:
a
b
c
d
e
f
g
s
r
x
%
A
E
F
G
X
hexadecimal floating point (uppercase)
binary
Unicode character
decimal
exponential float (uppercase)
floating point (uppercase)
exponential/floating point
string
representation
hexadecimal (uppercase)
percent sign
Table 16: Formatting conversion types
.text format("%#04x bytes left", 1000); $03e8 bytes left
len()
Returns the number of elements.
bit string
character string
byte string
tuple, list
dictionary
code
len($034) is 12
length in bits
len("abc") is 3
number of characters
len(b"abc") is 3
number of bytes
len([1, 2, 3]) is 3
number of elements
len({1:2, 3:4]) is 2
number of elements
len(label)
number of elements
Table 17: Length of various types
random([, …])
Returns a pseudo random number.
The sequence does not change across compilations and is the same every time. Differ‐
ent sequences can be generated by seeding with .seed.
random()
floating point number 0.0 <= x < 1.0
random(e)
integer in range of 0 <= x < e
random(s, a)
integer in range of s <= x < e
random(s, a, t)
integer in range of s <= x < e, step t
Table 18: Random function invocation types
.seed 1234
; default is boring, seed the generator
17 / 68
64tass v1.53 r1515 reference manual
.byte random(256); a pseudo random byte (0..255)
.byte random([16] x 8); 8 pseudo random bytes (0..15)
range([, , …])
Returns a list of integers in a range, with optional stepping.
range(e)
integers from 0 to e−1
range(s, a)
integers from s to e−1
range(s, a, t)
integers from s to e (not including e), step t
Table 19: Range function invocation types
mylist
.byte range(16) ; 0, 1, ..., 14, 15
.char range(-5, 6); -5, -4, ..., 4, 5
= range(10, 0, -2); [10, 8, 6, 4, 2]
repr()
Returns a string representation of value.
.warn repr(var) ; pretty print value, for debugging
size()
Returns the size of code, structure or union in bytes.
ldx #size(var) ; size to x
sort()
Returns a sorted list or tuple.
If the original list contains further lists then these must be all of the same length. In
this case the order of lists is determined by comparing their elements from the start
until a difference is found. The sort is stable.
; sort IRQ routines by their raster lines
sorted = sort([(60, irq1), (50, irq2)])
lines
.byte sorted[:, 0] ; 50, 60
irqs
.addr sorted[:, 1] ; irq2, irq1
3.15
Expressions
3.15.1 Operators
The following operators are available. Not all are defined for all types of arguments and their
meaning might slightly vary depending on the type.
−
!
∗
negative
not
convert to arguments
+
positive
~
invert
^
decimal string
Table 20: Unary operators
The “^” decimal string operator will be changed to mean the bank byte soon. Please
update your sources to use format("%d", xxx) instead! This is done to be in line with it's
use in most other assemblers.
+
∗
%
|
add
multiply
modulo
binary or
−
subtract
/
divide
∗∗
raise to power
^
binary xor
Table 21: Binary operators
18 / 68
64tass v1.53 r1515 reference manual
binary and
shift right
concat
contains
&
>>
..
in
<<
.
x
shift left
member
repeat
There's a ternary operator (? :) which gives the second value if the first is true or the third if
the first is false.
Parenthesis (( )) can be used to override operator precedence. Don't forget that they also
denote indirect addressing mode for certain opcodes.
lda #(4+2)*3
3.15.2 Comparison operators
Traditional comparison operators give false or true depending on the result.
The compare operator (<=>) gives −1 for less, 0 for equal and 1 for more.
compare
equals
less than
more than
<=>
==
<
>
!=
not equal
>=
more than or equals
<=
less than or equals
Table 22: Comparison operators
3.15.3 Bit string extraction operators
These unary operators extract 8 or 16 bits as a bit string from various types of operands.
<
<>
><
>
lower byte
higher byte
>`
lower word
higher word
`
lower byte swapped word
bank byte
Table 23: Bit string extraction operators
lda #
Source Exif Data:
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
PDF Version : 1.5
Linearized : Yes
Creator : cairo 1.9.5 (http://cairographics.org)
Producer : cairo 1.9.5 (http://cairographics.org)
Page Count : 68