Beruflich Dokumente
Kultur Dokumente
45
(c) 2000-2011 by The New Image
Programmed by Patriek Lesparre
http://tniasm.tni.nl/
e-mail: tniasm@tni.nl
--------------------------------------------------------------------------Chapter 1: Introduction
----------------------1.1 What is it?
tniASM is a cross assembler for Z80, R800 and GBZ80. Some of its
features are:
-
Multi-pass design
Conditional assembly
Local label mechanism
Extensive 32 bit expression parser with precedence levels
Source and binary file inclusion
Nestable block comments
Multi file output and file patching
1.2 Why?
Why would anyone write another assembler? Good question! First,
I needed to learn C and there's no better way to learn a new
language than to write a program in it you need. That brings me to
the second reason I wrote tniASM, which is that none of the other
cross assemblers I know had the features I wanted/needed.
Because of that, and perhaps the fact that I've never written a
assembler/compiler before, tniASM is not like other assemblers. It
has many peculiarities and frankly, you might find it a bit weird.
Nevertheless, it suits my purposes perfectly and I hope it does
yours too.
1.3 tniASM and Passes
Most assemblers have 2 passes, one to gather information on labels
and another to handle forward references and generate the output.
tniASM goes about it differently. The output generation is a pass
by itself, and before that tniASM will do as many passes as is
needed to evaluate all expressions.
Basically it means that tniASM will make 2 passes PLUS an extra
pass for every level of forward referencing, up to 5 passes total.
1.4 tniASM Assembler Syntax
tniASM has its own assembler syntax for the processors it supports.
Don't be alarmed though, the changes are minimal. See chapters
2.7 and on for differences between standard rules.
1.5 Using tniASM
{...}
ret
sub:
{...}
jp main.end
ret
.end:
Or the other way around, create labels that are local outside of
the scope of the current non-local label:
main:
ld
{...}
sub:
{...}
a,[.value]
main.value: db 0
2.2.2 The Line-seperator
The '|' character is used as a line seperator. You can use it to
have more than one instruction on a line. In fact the lineseperator is not needed most of the time, since tniASM can figure
out by itself that the line "add a,a call jump ret" are actually 3
different instructions. Seperating the instructions with '|' is
just nicer to look at and perhaps better to understand. However, in
a line like "add a,34 and 3 xor 255" tniASM assumes you mean
"add a,253" and not 3 seperate instructions. To make sure tniASM
generates the code you want, use the line-seperator.
2.2.3 More on Comments
As usual the semi-colon (';') is used as the comment-character. It
can be placed anywhere on a line and everthing behind it is ignored
until a new line.
Besides the normal comments, tniASM also supports comment blocks.
The '{' and '}' characters respectively mark the beginning and the
end of a comment-block. They can be placed anywhere in a file, and
everthing between them is ignored. Comment-blocks are nestable with
a practically infinite nesting depth.
2.3 Constants
There are 3 different kinds of constants in tniASM: numeric,
character and string. Since tniASM is a 32 bit assembler, constants
are 32 bit signed integer values, ranging from -2147483648
(80000000h) to 2147483647 (7FFFFFFFh).
2.3.1 Numeric Constants
Numeric constants can be represented in decimal, hexadecimal,
binary or octal. The supported forms are as follows:
Decimal
: 123
123d
Hexadecimal: 1234h (cannot start with a letter, use '0ABCDh' etc.)
$1234
0x1234
Binary
: 11100100b (may contain white space, ie. '1110 0100 b')
%11100100 ( " "
"
"
" '% 1110 0100')
Octal
: 123o
123q
2.3.2 String Constants
A string constant is anything between single or double qoutes
larger than 4 characters. They're used in commands like DB/DW,
INCLUDE and FNAME. String constants can not be used in regular
expressions.
example:
DB "a 'double-qouted' string can contain single qoutes"
DB 'and a "single-qouted" string can contain double qoutes'
2.3.3 Character Constants
Character constants follow the same rules as strings, except that
they can be used in expressions. They can be up to 4 characters in
size, and are stored low-byte first. The constant 'A' is thus
handled as 41h, 'AB' as 4241h (or 41h,42h), 'ABC' as 434241h
;
;
;
;
;
;
;
is 'a','b','c','d'.
is 'a','b'. Since both strings are inside
of an expression, they're treated as a
character constant.
is an error, because 'a' is not considered
to be inside the expression.
is 'b'
2.4 Expressions
Expressions are evaluated in 32 bit signed integer arithmetic. An
expression consists of one or more constants, combined with zero or
more operators. Two special tokens can be used in expressions: '$'
and '$$'. They are the assembly position (program counter) and file
position respectively, at the beginning of the current instruction.
One could code:
nop
nop
jr $-2 ; jump to the first nop
All supported operators are listed below, starting with the lowest
precedence-level. Operators with equal precedence are evaluated
from left to right.
Ofcourse any precedence can be overridden with the parenthesis '('
and ')'.
2.4.1 Precedence Level 0 - Relational Operators
The relational operators are:
x
x
x
x
x
x
x
x
x
x
= y
<> y
>< y
!= y
< y
> y
<= y
=< y
>= y
=> y
equals
not equals
"
"
"
"
less than
more than
less than or equals
"
" "
"
more than or equals
"
" "
"
Addition
Subtraction
x OR y Bitwise OR
x XOR y Bitwise XOR
2.4.3 Precedence Level 2 - Multiplicative and AND Operators
x
x
x
x
^ y
* y
/ y
MOD y
Exponentiation
Multiplication
Division
Modulo
unary plus
unary minus
one's complement
255
"bla",13,10
'AB',4000h
"string may be odd"
2.5.2 DC
Defines a string terminated by bit 7 being set.
DC
DC
"TOKEN"
"LIST","STOP"
2.5.3 DS
Define space (in bytes).
DS
DS
DS
DS
DS
2.5.4 EQU
10
10,255
4000h-$
0
-1
;
;
;
;
;
defines 10 bytes of 0
defines 10 bytes of 255
pad with 0 until address 4000h
doesn't do anything
the same goes for negative values
EQU 4000h
ORG bankstart
2.5.5 FNAME
Specify output file. Use FNAME to make tniASM output to a file
other than 'tniasm.out'. You can use FNAME as much as you like
throughout your source code in order to output different parts to
different files.
FNAME also sets FORG to 0.
FNAME "output.bin"
{...}
2.5.6 FORG
Set output file position. You can use FORG to cause tniASM to
output at a certain file position. If the position is larger than
the file it will be padded with 0's.
When no FORG is given, the starting file position will be 0.
2.5.7 INCBIN
Include binary file. The INCBIN instruction includes a binary file
in the current machine code output. It's particularly useful for
embedding graphics or large tables that you wouldn't want to have
in huge DB lists.
music1: INCBIN "music1.bin"
.end:
INCBIN optionally takes 1 or 2 more parameters. The first is the
offset in the file to be included. The second is the total length
of data to be included.
INCBIN "basic.bin",7
INCBIN "cutout.bin",1024,512
2.5.8 INCLUDE
The INCLUDE instruction includes another file in the current source
file, in nesting levels as deep as memory permits.
{...}
INCLUDE "incthis.asm"
{...}
2.5.9 ORG
ORG allows one or two arguments. The first sets the assembly
position (program counter) to an address, while the second argument
gives the maximum allowable address for this 'section'. If the
address is exceeded, tniASM will issue a warning. This warning
ignores any PHASE'ing.
When no ORG is given, the starting assembly position will be 0.
ORG 0c000h
ORG 0c000h,0
ORG 4000h,7FFFh
2.5.10 PHASE/DEPHASE
PHASE 'phases' the assembly position to the address specified. This
is particularly useful for code that gets relocated later. DEPHASE
phases back to the normal assembly position.
A new PHASE or ORG command DEPHASE's any previous PHASE'ing.
; this example relocates the routine SetS#0 from its current
; address to 0C000h. Because of the PHASE/DEPHASE its label
; 'SetS#0' already points to 0C000h.
ORG
8000h
ld
ld
ld
ldir
hl,start
de,SetS#0
bc,SetS#0.end-SetS#0.start
{...}
SetS#0.start:
PHASE
SetS#0: xor
out
ld
out
ret
DEPHASE
.end:
0C000h
a
[99h],a
a,15+128
[99h],a
2.5.11 RB/RW
Reserve a (number of) byte(s)/word(s) as uninitialised data. This
is basically the same as DS, but does not update the file position,
neither does it output anything. It merely updates the assembly
position. RB and RW are useful when declaring variables in RAM.
Var1:
Var2:
Var3:
Var4:
ORG
RB
RW
RB
RW
0C000h
2
1
0
-1
;
;
;
;
;
Var1 = 0C000h
Var2 = 0C002h
Var3 = 0C004h
Var4 = 0C004h because zero and
negative values are ignored
{...}
Z80
R800
MSX
GBZ80
;
;
;
;
- LD A,(n) and LD A,(C) (and vice versa) are written LDH A,[n] and
LDH A,[C]. Furthermore they have aliases IN A,[x] and OUT [x],A.
The LDH A,[n] and LDH [n],A can take values between 0-FF and
FF00-FFFF hex.
- ADD SP,d is written LD SP,SP+d.
- LDHL SP,d is written LD HL,SP+d.
- tniASM Z80 rules. (Chapter 2.7.1)
Chapter 3: Other Stuff
---------------------3.1 Tips and Tricks
The best tip I can give you when working with tniASM is to keep one
file in which you include every other file. Sort of like a makefile
without dependencies and object stuff.
; "example.asm"
; this is an example 'makefile'
fname
org
include
include
include
"example.com"
100h
"frontend.asm"
"main.asm"
"backend.asm"
fname
org
incbin
include
"example.dat"
0
"stuff.dat"
"somesubs.asm"
3.2 History
2 November 2011, v0.45 Magnum mercy shot
- Fixed: Generate error for LD L,IXL (or similar) instead of simply
outputting LD IXL,IXL.
- Now supports using expressions for the fixed numeric operands in
IM, RST, BIT, RES and SET instructions. Previously generated an
error or wrong result!
- Officially the last version of the v0.x series. See Chapter 3.3
for information about tniASM v1.0.
2 March 2005, v0.44
- Fixed: $ during PHASE
22 January 2005, v0.43
- The operator != is now supported as an alias for <>.
- Fixed: A bug concerning IF-ELSE sometimes caused errors.
- Updates in the manual (Chapter 2.7.2, 3.3)
14 November 2004, v0.42
- Fixed: A nested IF in an IF block that resolved as false caused
an infinite loop.
- Fixed: Defining a local label without a parent label now returns
an error message.