Please Note: I have merged this project with its sister project, 6502.Net, and it will now no longer be maintained.
The z80DotNet Macro Assembler is a simple cross-assembler targeting the Zilog Z80 and compatible CPU. It is written for .Net (Version 4.5.1) and supports all of the published (legal) instructions of the Z80 processor, as well as most of the unpublished (illegal) operations. Like the MOS 6502, the Z80 was a popular choice for video game system and microcomputer manufacturers in the 1970s and mid-1980s. For more information, see wiki entry or Z80 resource page to learn more about this microprocessor.
The z80DotNet assembler is simple to use. Invoke it from a command line with the assembly source and (optionally) the output filename in the parameters. A z80DotNet.exe myprg.asm
command will output assembly listing in myprgm.asm
to binary output. To specify output file name use the -o <file>
or --output=<file>
option, otherwise the default output filename will be a.out
.
You can specify as many source files as assembly input as needed. For instance, z80DotNet.exe mylib.asm myprg.asm
will assemble both the mylib.asm
and myprgm.asm
files sequentially to output. Be aware that if both files define the same symbol an assembler error will result.
All assembly statements are composed of ASCII or Unicode text. Statements are terminated by a carriage return:
ld a,0
Multiple statements per line are allowed; they are separated by a colon (:
) character:
ld (hl),MESSAGE:call STDOUT ; multiple statement line
Semi-colons denote the beginning of line comments, and remaining line text will not be processed by the assembler.
Integral constants can be expressed as decimal, hexadecimal, and binary. Decimal numbers are written as is, while hex numbers are prefixed with a $
and binary numbers are prefixed with a %
.
65490 = 65490
$ffd2 = 65490
%1111111111010010 = 65490
Negative numbers are assembled according to two's complement rules, with the highest bits set. Binary strings can alternatively be expressed as .
for 0
and #
for 1
, which is helpful for laying out pixel data:
number1 .byte %...###..
.byte %..####..
.byte %.#####..
.byte %...###..
.byte %...###..
.byte %...###..
.byte %...###..
.byte %.#######
When writing assembly, hand-coding branches, addresses and constants can be time-consuming and lead to errors. Labels take care of this work for you! There is no restriction on name size, but all labels must begin with an underscore or letter, and can only contain underscores, letters, and digits, and they cannot be re-assigned:
yellow = 6
ld a,yellow ; load yellow into acc.
jr nz,setborder ; now set the border color
...
setborder: call $229b ; poke border color with acc.
Trailing colons for labels are optional.
Once labels are defined they cannot be redinfed in other parts of code. This gets tricky as source grows, since one must choose a unique name for each label. There are a few ways to avoid this problem.
routine1 ld a,(hl)
jr z,_done
call stdout
inc hl
jr routine1
_done ret
routine2 ld c,flag
jr z,_done
jp dosomething
_done ret
In the routine above, there are two labels called _done
but the assembler will differentiate between them, since the second _done
follows a different non-local label than the first.
The first is to append the label with an underscore, making it a local label.
In addition to local labels, scope blocks can be used. All source inside a pair of .block
and .endblock
directives are considered local to that block, but can also be nested, making them much like namespaces.
A scope block looks like this:
...
endloop ld a,$ff
ret
myblock .block
call endloop ; accumulator will be 0
... ; since endloop is local to myblock
endloop xor a
ret
.endblock
Labels inside named scopes can be referenced with dot notation:
speccy .block
key_in = $10a8
wait_key = $15d4
.endblock
call speccy.key_in ; call the subroutine whose label
; is defined in the speccy block
Any block not preceded by a label is an anonymous block. All symbols inside an anonymous block are only visible within the block, and are unavailable outside:
.block
call inc32
...
inc32 inc bc
jr z,done
inc de
done ret
.endblock
call inc32 ; will produce an assembler error
Anonymous labels allow one to do away with the need to think of unique label names altogether. There are two types of anonymous labels: forward and backward. Forward anonymous labels are declared with a +
, while backward anonymous labels are declared using a -
. They are forward or backward to the current assembly line and are referenced in the operand with one or more +
or -
symbols:
- ld a,(ix+$00)
jr nz,+ ; jump to first forward anonymous from here
ld a,' '
+ rst $10
inc ix
rlca
jr nc,- ; jump to first backward anonymous from here
add a,a
jr nc,+ ; jump to first forward anonymous from here
and %01111111
jr ++ ; jump to second forward anonymous from here
+ ld (ix+$10),a
ret
+ ld (ix+$20),a
ret
As you can see, anonymous labels, though convenient, would hinder readability if used too liberally. They are best for small branch jumps, though can be used in the same was as labels:
- .byte $01, $02, $03
ld a,(-) ; put anonymous label reference inside paranetheses.
Another type of named symbol besides a label is a variable. Variables, like labels, are named references to values in operand expressions, but whose value can be changed as often as required. A variable is declared with the .let
directive, followed by an assignment expression. Variables and labels cannot share the same symbol name.
.let myvar = 34
ld a,myvar
.let myvar = myvar + 1
ld b,myvar
Unlike labels, variables cannot be referenced in other expressions before they are declared, since variables are not preserved between passes.
.let y = x
.let x = 3
In the above example, the assembler would error assuming x
has never been declared before.
Adding comments to source promotes readability, particularly in assembly. Comments can be added to source code in one of two ways, as single-line trailing source code, or as a block. Single-line comments start with a semi-colon. Any text written after the semi-colon is ignored, unless it is being expressed as a string or constant character.
xor a,a ; 0 = color black
call $2294 ; set border color to accumulator
ld a,';' ; the first semi-colon is a char literal so will be assembled
rst $10
Block comments span multiple lines, enclosed in .comment
and .endcomment
directives. These are useful when you want to exclude unwanted code:
.comment
this will set the cpu on fire do not assemble!
ld a,-1
ld ($5231),a
.endcomment
In addition to z80 assembly, data can also be assembled. Expressions evaluate internally as 64-bit signed integers, but must fit to match the expected operand size; if the value given in the expression exceeds the data size, this will cause an illegal quantity error. The following pseudo-ops are available:
Directive | Size |
---|---|
.byte |
One byte unsigned |
.sbyte |
One byte signed |
.addr |
Two byte address |
.sint |
Two bytes signed |
.word |
Two bytes unsigned |
.lint |
Three bytes signed |
.long |
Three bytes unsigned |
.dint |
Four bytes signed |
.dword |
Four bytes unsigned |
.align |
Zero or more bytes |
.fill |
One or more bytes |
Multi-byte directives assemble in little-endian order (the least significant byte first), which conforms to the z80 architecture. Data is comma-separated, and each value can be a constant or expression:
sprite .byte %......##,%########,%##......
jump .word sub1, sub2, sub3, sub4
For .fill
and .align
, the assembler accepts either one or two arguments. The first is the quantity, while the second is the value. If the second is not given then it is assumed to be uninitialized data (see below). For .fill
, quantity is number of bytes, for .align
it is the number of bytes by which the program counter can be divided with no remainder:
unused .fill 256,0 ; Assemble 256 bytes with the value 0
atpage .align 256 ; The program counter is guaranteed to be at a page boundary
Sometimes it is desirable to direct the assembler to make a label reference an address, but without outputting bytes at that address. For instance, program variables. Use the ?
symbol instead of an expression:
highscore .dword ? ; set the symbol highscore to the program counter,
; but do not output any bytes
Note that if uninitialized data is defined, but thereafter initialized data is defined, the output will fill bytes to the program counter from the occurrence of the uninitialized symbol:
highscore .dword ? ; uninitialized highscore variables
xor a,a ; The output is now 6 bytes in size
Use the .typedef
directive to redefine a type name. This is useful for cross- and backward-compatibility with other assemblers. Each type can have more than one definition.
.typedef .byte, db
.typedef .byte, defb ; multiple okay
.typedef .string, asc
Only pseudo operations can have their types redefined. For mnemonics or other assembler directives consider using macros instead.
In addition to integral values, z80DotNet can assemble Unicode text. Text strings are enclosed in double quotes, character literals in single quotes.
Strings can be assembled in a few different ways, according to the needs of the programmer.
Directive | Meaning |
---|---|
.string |
A standard string literal |
.cstring |
A C-style null-terminated string |
.lsstring |
A string with output bytes left-shifted and the low bit set on its final byte |
.nstring |
A string with the negative (high) bit set on its final byte |
.pstring |
A Pascal-style string, its size in the first byte |
Since .pstring
strings use a single byte to denote size, no string can be greater than 255 bytes. Since .nstring
and .lsstring
make use of the high and low bits, bytes must not be greater in value than 127, nor less than 0.
The special function format()
function allows you to convert non-string data to string data using a .Net format string:
stdout = $ffd2
stdstring .string format("The stdout routine is at ${0:X4}", stdout)
;; will assemble to:
;; "The stdout routine is at $FFD2
Many traditional assemblers allow programmers to use their character and value string pseudo-ops interchangeably, e.g. .byte "HELLO"
and .asc "HELLO"
. Note that z80DotNet treats character strings differently for the .byte
and other value-based commands. For these pseudo-ops string characters are compacted, while the pseudo-op length is enforced:
.byte "H" ; okay
.dword "HELLO" ; also okay, .dword can accomodate 4 ASCII bytes
.byte 'H','I' ; still ok--two different literals
.byte "HELLO" ; will error out
Generally, it is best to use the string commands for processing character string literals, and the value commands for multibyte values.
Assembly source text is processed as UTF-8, and by default strings and character literals are encoded as such. You can change how text output with the .encoding
and .map
directives. Use .encoding
to select an encoding. The encoding name follows the same rules as labels.
The default encoding is none
.
Text encodings are modified using the .map
and .unmap
directives. After selecting an encoding, you can map a Unicode character to a custom output code as follows:
;; select encoding
.encoding myencoding
;; map A to output 0
.map "A", 0
.string "ABC"
;; > 00 42 43
;; char literals are also affected
ld a,'A' ;; 3e 00
;; emoji will assemble too!
.string "😁" ;; f0 9f 98 81
The output can be one to four bytes. Entire character sets can also be mapped, with the re-mapped code treated as the first in the output range. The start and endpoints in the character set to be re-mapped can either be expressed as a two-character string literal or as expressions.
;; output lower-case chars as uppercase
.map "az", "A"
;; output digits as actual integral values
.map "0","9", 0
;; alternatively:
.map 48, 48+9, 0
;; escape sequences are acceptable too:
.map "\u21d4", $9f
Caution: Operand expressions containing a character literal mapped to a custom code will evaluate the character literal accordingly. This may produce unexpected results:
.map 'A', 'a'
.map 'a', 'A' ;; this is now the same as .map 'a', 'a'
Instead express character literals as one-character strings in double-quotes, which will evaluate to UTF-8 code units.
A further note about encodings and source files. As mentioned, source files are read and processed as UTF-8. While it is true that the .Net StreamReader class can auto-detect other encodings, this cannot be guaranteed (for instance if the BOM is lacking in a UTF-16-encoded source). If the source does not assemble as expected, consider converting it to UTF-8 or at least ASCII. This article offers a good overview on the issues concerning text encodings.
Most .Net escape sequences will also output, including Unicode.
.string "He said, \"How are you?\""
.byte '\t', '\''
Here are a few recognized escape sequences:
Escape Sequence | ASCII/Unicode Representation |
---|---|
\n |
Newline |
\r |
Carriage return |
\t |
Tab |
\" |
Double quotation mark |
\unnnn |
Unicode U+nnnn |
Other files can be included in final assembly, either as z80DotNet-compatible source or as raw binary. Source files are included using the .include
and .binclude
directives. This is useful for libraries or other organized source you would not want to include in your main source file. The operand is the file name (and path) enclosed in quotes. .include
simply inserts the source at the directive.
;; inside "../lib/library.s"
.macro inc16 reg16
inc (\reg16)
jr nz +
inc \reg16
inc (\reg16)
+ .endmacro
...
This file called "library.s"
inside the path ../lib
contains a macro definition called inc16
(See the section below for more information about macros).
.include "../lib/library.s"
.inc16 $c000 ; 16-bit increment value at $033c and $033d
If the included library file also contained its own symbols, caution would be required to ensure no symbol clashes. An alternative to .include
is .binclude
, which resolves this problem by enclosing the included source in its own scoped block.
lib .binclude "../lib/library.s" ; all symbols in "library.s"
; are in the "lib" scope
call lib.memcopy
If no label is prefixed to the .binclude
directive then the block is anonymous and labels are not visible to your code.
External files containing raw binary that will be needed to be included in your final output, such as graphics data, can be assembled using the .binary
directive.
* = $1000
.binary "../rsrc/gfx.bin"
You can also control how the binary will be included by specifying the offset (number of bytes from the start) and size to include.
* = $1000
charA:
.binary "../rsrc/charset.bin",0,64
charB:
.binary "../rsrc/charset.bin",64,64
charC:
.binary "../rsrc/charset.bin",128,64
...
* = $c000
;; copy charA glyph graphics to $4000
ld hl,charA
ld de,$4000
ld bc,64
ldir
All non-string operands are treated as math or conditional expressions. Compound expressions are nested in paranetheses. There are several available operators for both binary and unary expressions. The order of operation generally follows that the .Net languages for matching operators, with the byte extractors taking highest precedence.
Operator | Meaning |
---|---|
+ | Add |
- | Subtract |
* | Multiply |
/ | Divide |
% | Modulo (remainder) |
** | Raise to the power of |
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise XOR |
<< | Bitwise left shift |
>> | Bitwise right shift |
< | Less than |
<= | Less than or equal to |
== | Equal to |
!= | Not equal to |
>= | Greater than or equal to |
> | Greater than |
&& | Logical AND |
|| | Logical OR |
.addr HIGHSCORE + 3 * 2 ; the third address from HIGHSCORE
.byte * > $f000 ; if program counter > $f000, assemble as 1
; else 0
;; bounds check START_ADDR
.assert START_ADDR >= MIN && START_ADDR <= MAX
Operator | Meaning |
---|---|
~ | Bitwise complementary |
< | Least significant byte |
> | Most significant (second) byte |
^ | Bank (third) byte |
! | Logical NOT |
ld h, #>routine ; routine MSB
ld l, #<routine ; routine LSB
jp (hl)
Several built-in math functions that can also be called as part of the expressions.
ld a,sqrt(25)
See the section below on functions for a full list of available functions.
The math constants π and e are defined as MATH_PI
and MATH_E
, respectively, and can be referenced in expressions as follows:
.dword sin(MATH_PI/3) * 10 ; > 08
.dword pow(MATH_E,2) ; > 07
Not that no labels or variables can share these two names as they are reserved.
By default, programs start at address 0, but you can change this by setting the program counter before the first assembled byte. While many Z80 assemblers used $
to denote the program counter, z80DotNet uses the *
symbol. The assignment can be either a constant or expression:
* = ZP + 1000 ; program counter now 1000 bytes offset from
; the value of the constant ZP
(Be aware of the pesky trap of trying to square the program counter using the **
operator, i.e. ***
. This produces unexpected results. Instead consider the pow()
function as described in the section on math functions below.)
As assembly continues, the program counter advances automatically. You can manually move the program counter forward, but keep in mind doing so will create a gap that will be filled if any bytes are added to the assembly from that point forward. For instance:
* = $1000
xor a
call $1234
* = $1fff
rst $38
Will output 4096 bytes, with 4091 zeros.
To move the program counter forward for the purposes having the symbols use an address space that code will be relocated to later, you can use the .relocate
directive:
* = $0200
newlocation = $a000
ld hl,torelocate
ld de,newlocation
ld bc,torelocate_end - torelocate
ldir
....
torelocate:
.relocate newlocation ; no gap created
call relocatedsub ; now in the "newlocation" address space
...
relocatedsub
xor a
...
To reset the program counter back to its regular position use the .endrelocate
directive:
call relocatedsub
...
jp finish
torelocate:
relocate newlocation
...
.endrelocate
torelocate_end
;; done with movable code, do final cleanup
finish ret
One of the more powerful features of the z80DotNet cross assembler is the ability to re-use code segments in multiple places in your source. You define a macro or segment once, and then can invoke it multiple times later in your source; the assembler simply expands the definition where it is invoked as if it is part of the source. Macros have the additional benefit of allowing you to pass parameters, so that the final outputted code can be easily modified for different contexts, behaving much like a function call in a high level language. For instance, one of the more common operations in z80DotNet assembly is to do a 16-bit increment. You could use a macro for this purpose like this:
inc16 .macro register
inc (\register)
jr nz,+
inc \register
inc (\register)
+ .endmacro
The macro is called inc16
and takes a parameter called register
. The code inside the macro consumes the parameters with a backslash \
followed by the parameter name. The parameter is a textual substitution; whatever you pass will be expanded at the reference point. Note the anonymous forward symbol at the branch instruction will be local to the block, as would any symbols inside the macro definition when expanded. To invoke a macro simply reference the name with a .
in front:
myvariable .word ?
ld hl,myvariable
.inc16 hl ; do a 16-bit increment of myvariable
This macro expands to:
inc (hl)
jr nz,+
inc hl
inc (hl)
+ ...
Parameter insertions also work in string literals, but the parameter formatting is more like a .Net string format with a @
symbol in front:
hello .macro name
.string "Hello, @{name}."
.endmacro
Parameters can be referenced by number in this way:
today .macro
.string "Today is @{1}"
.endmacro
;; Expansion of ".today Tuesday""
.string "Today is Tuesday"
Segments are conceptually identical to macros, except they do not accept parameters and are usually used as larger segments of relocatable code. Segments are defined between .segment
/.endsegment
blocks with the segment name after each closure directive, then
are declared into the source using the .dsegment
directive, followed by the segment name. Unlike macros, segments can be declared before they are defined.
.segment RAM
var1 .word ?
var2 .word ?
...
.endsegment RAM
.segment code
di
xor a
ld (IRQ_ENABLE),a
ld hl,RAM_START
ld bc,RAM_SIZE
rst $08
...
.endsegment code
Then you would assemble defined segments as follows:
* = $0000
.dsegment code
.errorif * > $3fff, ".code segment outside of ROM space!"
* = $4000
.dsegment RAM
You can also define segments within other segment definitions. Note that doing this does not make them "nested." The above example would be re-written as:
.segment program
.segment bss
var1 .word ?
var2 .word ?
txtbuffer .fill 256
.endsegment bss
.segment code
xor a
...
.segment hivars
variables .byte ?
...
.endsegment hivars
.endsegment code
.endsegment program
* = $0000
.dsegment code
* = $4000
.dsegment bss
* = $d000
.dsegment hivars
In cases where you want to control the flow of assembly, either based on certain conditions (environmental or target architecture) or in certain iterations, z80DotNet provides certain directives to handle this.
Conditional assembly is available using the .if
and related directive. Conditions can be nested, but expressions will be evaluated on first pass only.
In cases where you want to control the flow of assembly based on certain conditions (environmental or target architecture), z80DotNet provides certain directives to handle this. Conditions can be nested, but expressions will be evaluated on first pass only.
.ifdef ZXSPECTRUM
call setcolor
.else
nop
nop
nop
.endif
.if * > $7fff ; is program counter $8000 or more
.end ; terminate assembly
.endif ; end
Caution: Be careful not to use the .end
directive inside a conditional block, otherwise the .endif
closure will never be reached, and the assembler will report an error.
On occasions where certain instructions will be repeatedly assembled, it is convenient to repeat their output in a loop. For instance, if you want to pad a series of nop
instructions. The .repeat
directive does just that.
;; will assemble $ea ten times
.repeat 10
nop
.endrepeat
These repetitions can also be nested, as shown below.
;; print each letter of the alphabet 3 times
* = $1000
ld a,'A'
.repeat 26
.repeat 3
rst $10
.endrepeat
inc a
.endrepeat
.repeat 3
rst $10
.endrepeat
ret
Repetitions can also be handled in for/next loops, where source can be emitted repeatedly until a condition is met. The added advantage is the variable itself can be referenced inside the loop.
xor a,a
.for i = $0400, i < $0800, i = i + 1
ld (i),a
.next
A minimum two operands are required: The initial expression and the condition expression. A third iteration expression is option. The iteration expression can be blank, however.
.let a = 0;
.let n = 1;
.for , n < 10
.if a == 3
.let n = n + 1;
.else
.let n = n + 5;
.endif
.echo format("{0}",n);
.next
.comment
Outputs:
6
11
.endcomment
If required, loops can be broken out of using the .break
directive
.for i = 0, i < 256, i = i + 1
.if * >= $1000
.break ; make sure assembly does not go past $1000
.endif
ld a,'A'
rst $10
.next
All expressions, including the condition, are only evaluated on the first pass.
Caution: Changing the value of the iteration variable inside the loop can cause the application to hang. z80DotNet does not restrict re-assigning the iteration variable inside its own or nested loops.
z80DotNet supports all legal and (virtual all) illegal instruction types, including the so-called IXCB
instructions (e.g. set 0,(ix+$00),b
). Please consult the official Z80 User Manual for more information on general Z80 programming.
Following is the detail of each of the z80DotNet pseudo operations, or psuedo-ops. A pseudo-op is similar to a mnemonic in that it tells the assembler to output some number of bytes, but different in that it is not part of the CPU's instruction set. For each pseudo-op description is its name, any aliases, a definition, arguments, and examples of usage. Optional arguments are in square brackets ([
and ]
).
Note that every argument, unless specified, is a legal mathematical expression, and can include symbols such as labels (anonymous and named) and the program counter. Anonymous labels should be referenced in parantheses, otherwise the expression engine might misinterpret them. If the expression evaluates to a value greater than the maximum value allowed by the pseudo-op, the assembler will issue an illegal quantity error.
Data/text insertions
Name | .addr |
Alias | .word |
Definition | Insert an unsigned 16-bit value or values between 0 and 65535 into the assembly. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | address[, address2[, ...] |
Example |
* = $1000 mysub ld a,13 ; output newline rst $10 ret .addr mysub ; >1006 00 10 |
Name | .align |
Alias | None |
Definition | Set the program counter to a value divisible by the argument. If a second argument is specified, the expressed bytes will be outputted until the point the program counter reaches its new value, otherwise is treated as uninitialized memory. |
Arguments | amount[, fillvalue] |
Example |
* = $1023 .align $10,$ff ; >1023 ff ff ff ff ff ff ff ff ; >102b ff ff ff ff ff .byte $23 ; >1030 23 |
Name | .binary |
Alias | None |
Definition | Insert a file as binary data into the assembly. Optional offset and file size arguments can be passed for greater flexibility. |
Arguments | filename[, offset[, size] |
Example |
.binary "mybin.bin" ; include all of 'mybin.bin' .binary "routines.bin",19 ; skip program header 'routines.bin' .binary "subroutines.prg",19,1000 ;; skip header, take only ;; 1000 bytes thereafter. |
Name | .byte |
Alias | None |
Definition | Insert an unsigned byte-sized value or values between 0 and 255 into the assembly. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $0400 .byte $39, $38, $37, $36, $35, $34, $33, $32, $31 ;; >0400 39 38 37 36 35 34 33 32 ;; >0408 31 |
Name | .cstring |
Alias | None |
Definition | Insert a C-style null-terminated string into the assembly. Multiple arguments can be passed, with a null only inserted at the end of the argument list. If ? is passed then the data is an uninitialized byte. Enclosed text is assembled as string-literal while expressions are assembled to the minimum number of bytes required for storage, in little-endian byte order. |
Arguments | value[, value[, ...] |
Example |
* = 1000 .cstring "hello, world!" ; >1000 68 65 6c 6c 6f 2c 20 77 ; >1008 6f 72 6c 64 21 00 .cstring $cd,$2000 ; >1019 cd 00 20 |
Name | .dint |
Alias | None |
Definition | Insert a signed 32-bit value or values between −2147483648 and 2147483647 into the assembly, little-endian Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $4000 .dint 18000000 ; >4000 80 a8 12 01 |
Name | .dword |
Alias | None |
Definition | Insert a signed 32-bit value or values between 0 and 4294967295 into the assembly, little-endian. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $f000 .dword $deadfeed ; >f000 ed fe ad de |
Name | .fill |
Alias | None |
Definition | Fill the assembly by the specified amount. Similar to align, that if only one argument is passed then space is merely reserved. Otherwise the optional second argument indicates the assembly should be filled with bytes making up the expression, in little-endian byte order. |
Arguments | amount[, fillvalue] |
Example |
.fill 23 ; reserve 23 bytes * = $1000 .fill 11,$ffd2 ; >1000 d2 ff d2 ff d2 ff d2 ff ; >1008 d2 ff d2 |
Name | .lint |
Alias | None |
Definition | Insert a signed 24-bit value or values between -8388608 and 8388607 into the assembly, little-endian. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $3100 .lint -80000 ; >3100 80 c7 fe |
Name | .long |
Alias | None |
Definition | Insert a signed 24-bit value or values between 0 and 16777215 into the assembly, little-endian. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $8100 .long $ffdd22 ; >8100 22 dd ff |
Name | .lsstring |
Alias | None |
Definition | Insert a string into the assembly, each byte shifted to the left, with the lowest bit set on the last byte. See example of how this format can be used. If the highest bit in each value is set, the assembler will error. Multiple arguments can be passed, with a null only inserted at the end of the argument list. If ? is passed then the data is an uninitialized byte. Enclosed text is assembled as string-literal while expressions are assembled to the minimum number of bytes required for storage, in little-endian byte order. |
Arguments | value[, value[, ...] |
Example |
and a ; clear carry ld de,screenbuf ld hl,message - ld a,(hl) ; next char rrca ; shift right ld (de),a ; save in buffer jr c,done ; carry set on shift? done inc hl ; else next char inc de ; and buff jr - ; get next done ret message .lsstring "HELLO" |
Name | .nstring |
Alias | None |
Definition | Insert a string into the assembly, the negative (highest) bit set on the last byte. See example of how this format can be used. If the highest bit on the last byte is already set, the assembler will error. Multiple arguments can be passed, with a null only inserted at the end of the argument list. If ? is passed then the data is an uninitialized byte. Enclosed text is assembled as string-literal while expressions are assembled to the minimum number of bytes required for storage, in little-endian byte order. |
Arguments | value[, value[, ...] |
Example |
ld hl,message ld de,screenbuf - ld a,(hl) ld b,a ; copy to b to test high bit and a,%01111111 ; turn off high bit... ld (de),a ; and print rlc b ; high bit into carry flag jr c,done ; if set we printed last char inc hl ; else increment pointers inc de jr - ; get next done ret message .nstring "hello" |
Name | .pstring |
Alias | None |
Definition | Insert a Pascal-style string into the assembly, the first byte indicating the full string size. Note this size includes all arguments in the expression. If the size is greater than 255, the assembler will error. If ? is passed then the data is an uninitialized byte. Enclosed text is assembled as string-literal while expressions are assembled to the minimum number of bytes required for storage, in little-endian byte order. |
Arguments | value[, value[, ...] |
Example |
* = $4000 .pstring $23,$24,$25,$26,1024 ; >4000 06 23 24 25 26 00 04 .pstring "hello" ; >4007 05 68 65 6c 6c 6f |
Name | .sbyte |
Alias | None |
Definition | Insert an unsigned byte-sized value or values between -128 and 127 into the assembly. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $0400 .sbyte 127, -3 ; >0400 7f fd |
Name | .sint |
Alias | None |
Definition | Insert a signed 16-bit value or values between -32768 and 32767 into the assembly, little-endian. Multiple arguments can be passed as needed. If ? is passed then the data is uninitialized. |
Arguments | value[, value[, ...] |
Example |
* = $1000 .sint -16384 ; >1006 00 c0 |
Name | .string |
Alias | None |
Definition | Insert a string into the assembly. Multiple arguments can be passed. If ? is passed then the data is an uninitialized byte. Enclosed text is assembled as string-literal while expressions are assembled to the minimum number of bytes required for storage, in little-endian byte order. |
Arguments | value[, value[, ...] |
Example |
* = 1000 .string "hello, world!" ; >1000 68 65 6c 6c 6f 2c 20 77 ; >1008 6f 72 6c 64 21 |
Assembler directives
Name | .assert |
Alias | None |
Definition | Asserts the truth of a given expression. If the assertion fails, an error is logged. A custom error can be optionally be specified. |
Arguments | condition[, error] |
Example |
* = $0800 nop .assert 5 == 6 ; standard assertion error thrown .assert * < $0801, "Uh oh!" ; custom error output |
Name | .binclude |
Alias | None |
Definition | Include a source file and enclose the expanded source into a scoped block. The specified file is z80DotNet-compatible source. If no name is given in front of the directive then all symbols inside the included source will be inaccessible. |
Arguments | filename |
Example |
soundlib .binclude "sound.s" call soundlib.play ; Invoke the ; play subroutine ; inside the ; sound.s source ;; whereas... .binclude "sound.s" call play ; will not assemble! |
Name | .block /.endblock |
Alias | None |
Definition | Define a scoped block for symbols. Useful for preventing label definition clashes. Blocks can be nested as needed. Unnamed blocks are considered anonymous and all symbols defined within them are inaccessible outside the block. Otherwise symbols inside blocks can be accessed with dot-notation. |
Arguments | None |
Example |
rom .block stdin = $10a8 stdout = $15ef .endblock ... stdout ld a,(hl) call rom.stdout ; this is a different ; stdout! done ret ; this is not the done ; below! .block jr z,done ; the done below! nop nop done ret .endblock |
Name | .break |
Alias | None |
Definition | Break out of the current for-next loop. |
Arguments | None |
Example |
.for n = 0, n < 1000, n = n + 1 .if * > $7fff ; unless address >= $8000 .break .endif nop ; do 1000 nops .next |
Name | .comment /.endcomment |
Alias | None |
Definition | Set a multi-line comment block. |
Arguments | None |
Example |
.comment My code pre-amble .endcomment |
Name | .dsegment |
Alias | None |
Definition | Declare a segment to be used in code. The segment declaration can precede its definition in the .segment /.endsegment block.
|
Arguments | Segment name |
Example |
.dsegment code ; > 06 0f .segment code ld b,$0f .endsegment |
Name | .echo |
Alias | None |
Definition | Send a message to the console output. Note if the assembler is in quiet mode, no output will be given. |
Arguments | message |
Example |
.echo "hi there!" ;; console will output "hi there!" |
Name | .encoding |
Alias | None |
Definition | Select the text encoding for assembly output. The default is none , which is not affected by .map and .unmap directives.
|
Arguments | encoding |
Example |
.encoding petscii .string "hello" ; >> 45 48 4c 4c 4f |
Name | .end |
Alias | None |
Definition | Terminate the assembly. |
Arguments | None |
Example |
call $15ef jr z,done ; oops! ret .end ; stop everything done ... ; assembly will never ; reach here! |
Name | .eor |
Alias | None |
Definition | XOR output with 8-bit value. Quick and dirty obfuscation trick. |
Arguments | xormask |
Example |
.eor $ff .byte 0,1,2,3 ; > ff fe fd fc |
Name | .equ |
Alias | = |
Definition | Assign the label, anonymous symbol, or program counter to the expression. Note that there is an implied version of this directive, such that if the directive and expression are ommitted altogether, the label or symbol is set to the program counter. |
Arguments | value |
Example |
stdin .equ $10a8 stdout = $15ef * .equ $5000 - = 255 start ; same as start .equ * xor a |
Name | .error |
Alias | None |
Definition | Prints a custom error to the console. The error is treated like any assembler error and will cause failure of assembly. |
Arguments | error |
Example |
.error "We haven't fixed this yet!"
|
Name | .errorif |
Alias | None |
Definition | Prints a custom error to the console if the condition is met. Useful for sanity checks and assertions. The error is treated like any assembler error and will cause failure of assembly. The condition is any logical expression. |
Arguments | condition, error |
Example |
* = $5000 nop .errorif * > $5001, "Uh oh!" ; if program counter ; is greater than 20481, ; raise a custom error |
Name | .[el]if[[n]def] /.endif |
Alias | None |
Definition | All source inside condition blocks are assembled if evaluated to true on the first pass. Conditional expressions follow C-style conventions. The following directives are available:
|
Arguments | condition |
Example |
* = $0400 cycles = 4 .if cycles == 4 nop .elif cycles == 16 nop nop .endif ;; will result as: ;; ;; nop |
Name | .for /.next |
Alias | None |
Definition | Repeat until codition is met. The iteration variable can be used in source like any other variable. Multiple iteration expressions can be specified. This operation is only performed on first pass. |
Arguments | [init_expression], condition[, iteration_expression[, ...] |
Example |
.let x = 0 .for pages = $100, pages < $800, pages = pages + $100, x = x + 1 ld a,x ld (pages),a .next |
Name | .include |
Alias | None |
Definition | Include a source file into the assembly. The specified file is z80DotNet-compatible source. |
Arguments | filename |
Example |
.include "mylib.s" ;; mylib is now part of source |
Name | .let |
Alias | None |
Definition | Declares and assigns or re-assigns a variable to the given expression. Labels cannot be redefined as variables, and vice versa. |
Arguments | expression |
Example |
.let myvar = $c000 call myvar .let myvar = myvar-$1000 ld a,(myvar) |
Name | .macro /.endmacro |
Alias | None |
Definition | Define a macro that when invoked will expand into source. Must be named. Optional arguments are treated as parameters to pass as text substitutions in the macro source where referenced, with a leading either a backslash \ or as @{param} from within a string, either by name or by number in the parameter list. Parameters can be given default values to make them optional upon invocation. Macros are invoked with a leading . . All symbols in the macro definition are local, so macros can be re-used with no symbol clashes. |
Arguments | parameter[, parameter[, ...] |
Example |
inc16 .macro inc (\1) jr nz,+ inc \1 inc (\1) + .endmacro .inc16 hl ;; expands to => inc (hl) jr nz,+ inc hl inc (hl) + print .macro value = 13, printsub = $15ef ld a,\value ; or ld a,\1 call \printsub ; or call \2 ret .endmacro .print ;; expands to => ;; ld a,$0d ;; call $15ef ;; ret .print 'E',$0010 ;; expands to => ;; ld a,$45 ;; call $0010 ;; ret |
Name | .map |
Alias | None |
Definition | Maps a character or range of characters to custom binary output in the selected encoding. Note: none is not affected by .map and .unmap directives. It is recommended to represent individual char literals as strings.
|
Arguments | start[, end] /"<start><end>" ,code |
Example |
.encoding myencoding .map "A", "a" .map "π", $5e .byte 'A', 'π' ;; >> 61 5e .map "09", $00 .string "2017" ;; >> 02 00 01 07 |
Name | .relocate /.endrelocate |
Alias | .pseudopc /.realpc |
Definition | Sets the logical program counter to the specified address with the offset of the assembled output not changing. Useful for programs that relocate parts of themselves to different memory spaces. |
Arguments | address |
Example |
* = $5000 relocated = $6000 start ld hl,highcode ld de,relocated - ld bc,highcode_end-highcode ldir jp relocated highcode .relocate relocated ld hl,message printloop ld a,(hl) and a,a jr z,done call $15ef inc hl jr printloop done ret message .cstring "HELLO, HIGH CODE!" .endrelocate highcode_end ;; outputs the following: .comment >5000 21 0e 50 ; start ld hl,highcode >5003 11 00 60 ; ld de,relocated >5006 01 20 00 ; - ld bc,highcode_end-highcode >5009 ed b0 ; ldir >500b c3 00 60 ; jp relocated >500e 21 0e 60 ; ld hl,message >5011 7e ; printloop ld a,(hl) >5012 a7 ; and a,a >5013 28 06 ; jr z,done >5015 cd ef 15 ; call $15ef >5018 23 ; inc hl >5019 18 f6 ; jr printloop >501b c9 ; done ret ;; message >501c 48 45 4c 4c 4f 2c 20 48 >5024 49 47 48 20 43 4f 44 45 >502c 21 00 .endcomment |
Name | .repeat /.endrepeat |
Alias | None |
Definition | Repeat the specified source the specified number of times. Can be nested, but must be terminated with an .endrepeat . This operation is only performed on first pass. |
Arguments | repeatvalue |
Example |
* = $5000 xor a .repeat 3 inc a .endrepeat ret ;; will assemble as: ;; ;; xor a ;; inc a ;; inc a ;; inc a ;; ret |
Name | .segment /.endsegment |
Alias | None |
Definition | Defines a block of code as a segment, to be declared into source with the .dsegment directive. Segments are similar to macros but take no parameters and symbols are not local. Useful for building a large mix of source code and data without needing to relocate code manually. Segments can be defined within other segment block definitions, but are not considered "nested." Segment closures require the segment name after the directive. |
Arguments | segmentname |
Example |
.segment bss var1 .word ? var2 .word ? txtbuf .fill 256 .endsegment bss .segment highvar variables .dword ?, ?, ?, ? .endsegment highvar .segment code .segment data glyph ;12345678 .byte %....#### .byte %..#####. .byte %.#####.. .byte %#####... .byte %#####... .byte %.#####.. .byte %..#####. .byte %....#### .endsegment data di call init .endsegment code * = $8000 .dsegment bss * = $9000 .dsegment highvar * = $5000 .dsegment code * = $6000 .dsegment data |
Name | .target |
Alias | None |
Definition | Set the target architecture for the assembly output. See the --arch option in the command-line notes below for the available architectures. |
Arguments | architecture |
Example |
.target "zx" ;; the output binary will have an ZX Spectrum header ... |
Name | .typedef |
Alias | None |
Definition | Define an existing Pseudo-Op to a user-defined type. The type name adheres to the same rules as labels and variables and cannot be an existing symbol or instruction. |
Arguments | type, typename |
Example |
.typedef .byte, defb * = $c000 defb 0,1,2,3 ; >c000 00 01 02 03 |
Name | .unmap |
Alias | None |
Definition | Unmaps a custom code for a character or range of characters in the selected encoding and reverts to UTF-8. Note: none is not affected by .map and .unmap directives. It is recommended to represent individual char literals as strings.
|
Arguments | start[, end] /"<start><end>" |
Example |
.encoding myencoding .unmap "A" .unmap "π" ;; revert to UTF-8 encoding .byte 'A', 'π' ;; >> 41 cf 80 .unmap "09" .string "2017" ;; >> 32 30 31 37 |
Name | .warn |
Alias | None |
Definition | Prints a custom warning to the console. The warning is treated like any assembler warning, and if warnings are treated as errors it will cause failure of assembly. |
Arguments | warning |
Example |
.warn "We haven't fixed this yet!"
|
Name | .warnif |
Alias | None |
Definition | Prints a custom warning to the console if the condition is met. The warning is treated like any assembler warning, and if warnings are treated as errors it will cause failure of assembly The condition is any logical expression. |
Arguments | condition, warning |
Example |
* = $5000 nop .warnif * > $5001, "Check bound" ;; if program counter ;; is greater than 20481, ;; raise a custom warning |
Name | abs |
Definition | The absolute (positive sign) value of the expression. |
Arguments | value |
Example | .word abs(-2234) ; > ba 08 |
Name | acos |
Definition | The arc cosine of the expression. |
Arguments | value |
Example | .byte acos(1.0) ; > 00 |
Name | atan |
Definition | The arc tangent of the expression. |
Arguments | value |
Example | .byte atan(0.0) ; > 00 |
Name | cbrt |
Definition | The cubed root of the expression. |
Arguments | value |
Example | .long cbrt(2048383) ; > 7f 00 00 |
Name | ceil |
Definition | Round up expression. |
Arguments | value |
Example | .byte ceil(1.1) ; > 02 |
Name | cos |
Definition | The cosine of the expression. |
Arguments | value |
Example | .byte cos(0.0) ; > 01 |
Name | cosh |
Definition | The hyperbolic cosine of the expression. |
Arguments | value |
Example | .byte cosh(0.0) ; > 01 |
Name | deg |
Definition | Degrees from radians. |
Arguments | radian |
Example | .byte deg(1.0) ; > 39 |
Name | exp |
Definition | Exponential of e. |
Arguments | power |
Example | .dint exp(16.0) ; > 5e 97 87 00 |
Name | floor |
Definition | Round down expression. |
Arguments | value |
Example | .char floor(-4.8) ; > fb |
Name | format |
Definition | Converts objects to a string in the format specified. The format string must adhere to Microsoft .Net standards. Please see the documentation on standard .Net format strings for more information. |
Arguments | value |
Example | .echo format("Program counter is ${0:x4}", *) |
Name | frac |
Definition | The fractional part. |
Arguments | value |
Example | .byte frac(5.18)*100 ; > 12 |
Name | hypot |
Definition | Polar distance. |
Arguments | pole1, pole2 |
Example | .byte hypot(4.0, 3.0) ; > 05 |
Name | ln |
Definition | Natural logarithm. |
Arguments | value |
Example | .byte ln(2048.0) ; > 07 |
Name | log10 |
Definition | Common logarithm. |
Arguments | value |
Example | .byte log($7fffff) ; > 06 |
Name | pow |
Definition | Exponentiation. |
Arguments | base, power |
Example | .lint pow(2,16) ; > 00 00 01 |
Name | rad |
Definition | Radians from degrees. |
Arguments | degree |
Example | .word rad(79999.9) ; > 74 05 |
Name | random |
Definition | Generate a random number within the specified range of numbers. Both arguments can be negative or positive, but the second argument must be greater than the first, and the difference between them can be no greater than the maximum value of a signed 32-bit integer. This is a .Net limitation. |
Arguments | range1, range2 |
Example |
.word random(251,255) ; generate a random # between ; 251 and 255. |
Name | round |
Definition | Round number. |
Arguments | value, places |
Example | .byte round(18.21, 0) ; > 12 |
Name | sgn |
Definition | The sign of the expression, returned as -1 for negative, 1 for positive, and 0 for no sign. |
Arguments | value |
Example |
.char sgn(-8.0), sgn(14.0), sgn(0) ;; > ff 01 00 |
Name | sin |
Definition | The sine of the expression. |
Arguments | value |
Example | .char sin(1003.9) * 14 ; > f2 |
Name | sinh |
Definition | The hyperbolic sine of the expression. |
Arguments | value |
Example | .byte sinh(0.0) ; > f2 |
Name | sqrt |
Definition | The square root of the expression. |
Arguments | value |
Example | .byte sqrt(65536) - 1 ; > ff |
Name | str |
Definition | The expression as a text string. Only available for use with the string pseudo-ops. |
Arguments | value |
Example | .string str($c000) ; > 34 39 31 35 32 |
Name | tan |
Definition | The tangent the expression. |
Arguments | value |
Example | .byte tan(444.0)*5.0 ; > 08 |
Name | tanh |
Definition | The hyperbolic tangent the expression. |
Arguments | value |
Example | .byte tanh(0.0) ; > 00 |
z80DotNet accepts several arguments, requiring at least one. If no option flag precedes the argument, it is considered an input file. Multiple input files can be assembled. If no output file is specified, source is assembled to a.out
within the current working directory. Below are the available option flags and their parameters. Mono users note for the examples you must put mono
in front of the executable.
Option | -o |
Alias | --output |
Definition | Output the assembly to the specified output file. A valid output filename is a required parameter. |
Parameter | filename |
Example |
z80DotNet.exe myasm.asm -o myoutput z80DotNet.exe myasm.asm -output=myoutput |
Option | --arch |
Alias | None |
Definition | Specify the target architecture of the binary output. If architecture not specified, output defaults to flat . The options:
|
Parameter | architecture |
Example |
z80DotNet.exe myproggie.asm -b --arch=zx myproggie.prg |
Option | -b |
Alias | --big-endian |
Definition | Assemble multi-byte values in big-endian order (highest order magnitude first). |
Parameter | None |
Example |
z80DotNet.exe myasm.asm -b -o bigend.bin |
Option | -C |
Alias | --case-sensitive |
Definition | Set the assembly mode to case-sensitive. All tokens, including assembly mnemonics, directives, and symbols, are treated as case-sensitive. By default, z80DotNet is not case-sensitive. |
Parameter | None |
Example |
z80DotNet.exe mycsasm.asm -C z80DotNet.exe mycsasm.asm --case-sensitive |
Option | -D |
Alias | --define |
Definition | Assign a global label a value. Note that within the source the label cannot be redefined again. The value can be any expression z80DotNet can evaluate at assembly time. If no value is given the default value is 1. |
Parameter | <label>=<value> |
Example |
z80DotNet.exe -D label=$e000 myasm.asm -o myoutput |
Option | -h |
Alias | -?, --help |
Definition | Print all command-line options to console output. |
Parameter | None |
Example |
z80DotNet.exe -h z80DotNet.exe --help |
Option | -q |
Alias | --quiet |
Definition | Assemble in quiet mode, with no messages sent to console output, including errors and warnings. |
Parameter | None |
Example |
z80DotNet.exe -q myasm.asm z80DotNet.exe --quiet myasm.asm |
Option | -w |
Alias | --no-warn |
Definition | Suppress the display of all warnings. |
Parameter | None |
Example |
z80DotNet.exe -w myasm.asm z80DotNet.exe --no-warn myasm.asm |
Option | --werror |
Alias | None |
Definition | Treat all warnings as errors. |
Parameter | None |
Example |
z80DotNet.exe --werror myasm.asm |
Option | -l |
Alias | --labels |
Definition | Dump all label definitions to listing. |
Parameter | filename |
Example |
z80DotNet.exe myasm.asm -l labels.asm z80DotNet.exe myasm.asm --labels=labels.asm |
Option | -L |
Alias | --list |
Definition | Output the assembly listing to the specified file. |
Parameter | filename |
Example |
z80DotNet.exe myasm.asm -L listing.asm z80DotNet.exe myasm.asm --list=listing.asm |
Option | -a |
Alias | --no-assembly |
Definition | Suppress assembled bytes from assembly listing. |
Parameter | None |
Example |
z80DotNet.exe myasm.asm -a -L mylist.asm z80DotNet.exe myasm.asm --no-assembly --list=mylist.asm |
Option | -d |
Alias | --no-disassembly |
Definition | Suppress disassembly from assembly listing. |
Parameter | None |
Example |
z80DotNet.exe myasm.asm -d -L mylist.asm z80DotNet.exe myasm.asm --no-disassembly --list=mylist.asm |
Option | -s |
Alias | --no-source |
Definition | Do not list original source in the assembly listing. |
Parameter | None |
Example |
z80DotNet.exe myasm.asm -s -L mylist.asm z80DotNet.exe myasm.asm --no-source --list=mylist.asm |
Option | --verbose-asm |
Alias | None |
Definition | Make the assembly listing verbose. If the verbose option is set then all non-assembled lines are included, such as blocks and comment blocks. |
Parameter | None |
Example |
z80DotNet.exe myasm.asm --verbose-asm -L myverboselist.asm |
Option | -V |
Alias | --version |
Definition | Print the current version of z80DotNet to console output. |
Parameter | None |
Example |
z80DotNet.exe -V z80DotNet.exe --version |
Addressing mode is not supported for instruction
- The instruction does not support the addressing mode of the operand expression.
Assertion failed
- An assertion failed due to the condition evaluating as false.
Attempted to divide by zero.
- The expression attempted a division by zero.
Cannot redefine type to <type> because it is already a type
- The type definition is already a type.
Cannot resolve anonymous label
- The assembler cannot find the reference to the anonymous label.
Closure does not close a block
- A block closure is present but no block opening.
Closure does not close a macro
- A macro closure is present but no macro definition.
Closure does not close a segment
- A segment closure is present but no segment definition.
Could not process binary file
- The binary file could not be opened or processed.
Default parameter assignment error
- The parameter in the macro definition could not be a default value.
Directive takes no arguments
- An argument is present for a pseudo-op or directive that takes no arguments.
Duplicate paramater name found
- The macro definition contains one or more parameters that have already been defined.
Encoding is not a name or option
- The encoding selected is not a valid name.
error: invalid option
- An invalid option was passed to the command-line.
error: option requires a value
- An option was passed in the command-line that expected an argument that was not supplied.
<Feature> is depricated
- The instruction or feature is depricated (this is a warning by default).
Filename not specified
- A directive expected a filename that was not provided.
Format is invalid.
- The format string passed to format()
is not valid
General syntax error
- A general syntax error.
Illegal quantity
- The expression value is larger than the allowable size.
Invalid constant assignment
- The constant could not be assigned to the expression.
Invalid parameter reference
- The macro reference does not reference a defined parameter.
Invalid parameter(s)
- The parameters defined for the macro are not valid.
Invalid Program Counter assignment
- An attempt was made to set the program counter to an invalid value.
Label is not the leftmost character
- The label is not the leftmost character in the line (this is a warning by default).
Macro expects a value for parameter; no default value defined
- The macro expects a parameter that was not supplied.
Macro or segment is being called recursively
- A macro or segment is being invoked in its own definition.
Macro parameter not specified
- The macro expected a parameter that was not specified.
Macro parameter reference must be a letter or digit
- The macro parameter was in an invalid format.
Missing closure for block
- A block does not have a closure.
Missing closure for macro
- The macro does not have a closure.
Missing closure for segment
- A segment does not have a closure.
Parameter name invalid
- The parameter for the macro definition has an invalid name.
Program Counter overflow
- The program counter overflowed passed the allowable limit.
Pstring size too large
- The P-String size is more than the maximum 255 bytes.
Quote string not enclosed
- The quote string was not enclosed.
Redefinition of label
- A label is redefined or being re-assigned to a new value, which is not allowed.
Redefinition of macro
- An attempt was made to redefine a macro.
<Symbol> is not a valid symbol name
- The label or variable has one or more invalid characters.
Symbol not found
- The expression referenced a symbol that was not defined.
Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
- A format item in the format string passed to format()
does not match the parameter.
Too few arguments for directive
- The assembler directive expected more arguments than were provided.
Too many arguments for directive
- More arguments were provided to the directive than expected.
Too many characters in character literal
- The character literal has too many characters.
Type is unknown or not redefinable
- An attempt was made to define an unknown or non-definable type.
Type name is a reserved symbol name
- A type definition failed because the definition is a reserved name.
Unable to find binary file
- A directive was given to include a binary file, but the binary file was not found, either due to filesystem error or file not found.
Unable to open source file
- A source file could not be opened, either due to filesystem error or file not found.
Unknown architecture specified
- An invalid or unknown parameter was supplied to the --arch
option in the command-line.
Unknown instruction or incorrect parameters for instruction
- An directive or instruction was encountered that was unknown, or the operand provided is incorrect.
Unknown or invalid expression
- There was an error evaluating the expression.