This is an assembler for the DCPU-16 architecture as designed by Notch. This implements version 1.1 of the DCPU-16 standard. A copy of that standard is available in dcpu-16-v1.1.txt.
This assembler correctly supports short form labels, and it
automatically optimizes jump calls (
SET PC, value) to shorter
instructions if possible by default. This means that the compiled
binaries that this assembler produces are often slightly smaller and
run in fewer cycles than binaries produced by other assemblers given
the same source assembly.
This assembler also supports the DAT/DATA, BRK, JMP, BRA, RESERVE/.DS, TIMES/DUP, .INCBIN, and .INCLUDE meta-instructions that work on all DCPU-16 implementations, and it allows the user to specify custom new non-basic opcode instructions for use with supporting DCPU-16 implementations.
Simple constant arithmetic expressions are supported in instruction arguments. The following example code assembles fine:
:somelabel set a, [somelabel+1+b+5] dat 10, 10+5, 1+somelabel+0, 0 jmp 5+somelabel
Meta-instructions (or assembler directives) aren't actual instructions that are understood by the DCPU-16 architecture. They stand in for real instructions, or provide a way to place specific data into the compiled binary.
The DAT or DATA instruction is followed by data to put directly in the compiled binary. This data is a comma-delimited list of strings, characters, integers, and address labels.
The BRK instruction (break) signals for the program to end. Currently
this compiles to the same code that
SUB PC, 1 does.
The JMP instruction (jump) takes one argument: a label or address to
jump to. It is equivalent to using
SET PC, value, except that it
will automatically be replaced by
ADD PC, delta or
SUB PC, delta
if it is found that those instructions would be shorter. If
optimizations are enabled (which they are by default), then all
eligible uses of
SET PC, value in the source file will also be
considered for this optimization.
The BRA instruction (relative branch) is like the JMP instruction,
except it only ever compiles to the
ADD PC, delta or
SUB PC, delta
forms. This instruction is used for making position independent code
such that the binary can be loaded into any address and executed from
The RESERVE or .DS instruction takes one integer argument specifying
how many words of zeroes to reserve in memory at its location.
is equivalent to
DAT 0, 0, 0.
The TIMES or DUP instruction can be used immediately before a DAT
instruction with a number that tells how many times to repeat the DAT
TIMES 3 DAT 5 is equivalent to
DAT 5, 5, 5.
The .INCBIN instruction (include binary) is followed by a quoted
filename of a file to include into the compiled binary at this
location. The given pathname must be relative to the source file's
path. It is then followed by an optional endianness specifier, "THIS"
(default), "LE", or "BE". "THIS" specifies that the included file
should be read in the same endianness that this source file is being
compiled to, "LE" means it should be read in little endian form, and
"BE" means it should be read in big endian form. If the file is
included in the same endian form that the source file is being
compiled to, then the contents of the file will exactly match what is
written into the final binary. Example usage:
.incbin "some file.bin"
The .INCLUDE instruction is followed by a quoted filename of an
assembly file to include at this location. The source will be read as
if the included file's source was where the .INCLUDE instruction was
to begin with. Example usage:
The DCPU-16 standard defines a type of opcode ("non-basic opcode", or "NB-opcode" for short) that takes one argument. Only one NB-opcode is specified in the standard (JSR, with the value of 1).
Custom DCPU-16 implementations may implement other NB-opcodes, so this assembler allows the user to specify custom NB-opcodes and their values on the command line. The value of a custom NB-opcode must be between 2 and 63. The -n/--new-nbopcode options may be used (multiple times even) to specify the custom NB-opcodes. Look at the Usage section for examples.
Integers may be specified as a decimal value, or they may be specified in hexadecimal by prepending them with "0x" (i.e. "0x1f").
Source files are expected to be in UTF-8 format. If you don't use any non-7-bit characters, then normal ASCII format works as it is a subset of UTF-8. Both Unix and DOS style line endings are supported.
The Unicode code point value of a single character can be used where ever an integer is expected. Simply put the character in single quotes (i.e. 'a').
Strings may include Unicode characters, and they will be encoded into the compiled binary as UTF-16. Notch's DCPU-16 implementation in 0x10c may or may not natively support non-ASCII values.
This software project has compiled releases hosted at https://github.com/AgentME/DCPU-16-Assembler/downloads
(Make sure you download one of the named .zip files under the "Download Packages" section! The "Download as zip" and "Download as tar.gz" buttons just lead you to the project's source code.)
Java is required to use this assembler. On most platforms, the jar file can be run from the command line as follows:
java -jar DCPU16Assembler.jar
On Windows, the java executable may not be in your default search path. If the above line does not work, then find your Java installation's directory, and customize the following command to fit your system. The following command is not permanent and will only affect this current session:
set path=%path%;C:\Program Files (x86)\Java\jdk1.6.0_07\bin
If you got that right, then the following command should work now:
java -jar DCPU16Assembler.jar
Running it with no more arguments like that will cause it to show the usage instructions. To use it, pass the name of the source file:
java -jar DCPU16Assembler.jar myprogram.dasm16
By default, if the source file's name ends in ".dasm16", then compiled binary will be written to a file with the ".dcpu16" file extension. Otherwise, it will be written to a file named "a.out". You can specify an output filename by using a second argument:
java -jar DCPU16Assembler.jar myprogram.dasm16 other.dcpu16
Standard input or standard output can be used as the source file or output respectively by putting a - instead of a filename.
The -h/--help option can be given to show the usage instructions and list of options, and the --no-optimizations option can be given to disable all automatic optimizations while compiling.
The -p/--pic option causes all JMP instructions to be interpreted as
BRA instructions. Note that this option does not affect instructions
of the form
SET PC, value.
This assembler support writing its binaries in both little endian and big endian format. The assembler defaults to little endian format. The format may be specified with one of the -l/--little-endian or -b/--big-endian options. You may want to check which format(s) your DCPU-16 implementations support.
Custom NB-opcodes may be specified on the command line as follows with either the -n or --new-nbopcode arguments:
java -jar DCPU16Assembler.jar test.dasm16 -n print 17 -n clear 18
When those options are used, then "print" can be used in the source file just like other NB-opcodes like "jsr". Remember, these custom NB-opcodes are not meta-instructions that work everywhere; instead they are unstandard instructions that must be supported by your DCPU-16 implementation in order to be useful.
Copyright (C) 2012 Chris Cowan (firstname.lastname@example.org)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.