✓ Uses Rust 2018 edition
|0.1.1||Dec 21, 2019|
|0.1.0||Dec 21, 2019|
#8 in Emulators
Open-source Chip-8 assembler
ch8asm, pronounced like the word "chasm", is a simple-to-use and
easy-to-learn assembler for the Chip-8 retro video game platform. It
uses simple syntax and can easily be picked up in an afternoon or two.
Enter this command in your terminal to install
cargo install ch8asm
ch8asm <source file> at your terminal, replacing
<source file> with the path to your Chip-8 source code file. Assuming
nothing goes wrong (errors are described below), you will see a message
saying that your file was assembled correctly. Then, you can run the
resulting binary with your emulator of choice. If you don't have a
Chip-8 emulator already, you can use my emulator, Cookie, which can be
If you do not see the message
Successfully assembled <source file> into <binary file> when you try to assemble your game,
ch8asm will display
an error message saying what went wrong when assembling your binary. Here
are the possible error messages and their most likely fixes:
This message means that you attempted to use the label
defining it elsewhere in your program. Be sure to put a colon after the
definition of your label.
This message means that you used the wrong register
I register) in an instruction that doesn't support that
register. Be sure you are using the proper instruction arguments, as
This message means that you accidentally put a character in your
source code that
ch8asm doesn't recognize. Go to the line number
mentioned in the error message and look for a stray character.
This message means that you accidentally misspelled an instruction or tried to invent a new one. Go to the line number mentioned in the error message and check your code for proper spelling.
This message means that you have an out-of-place symbol in your code. Go to the line number mentioned in the error message and correct your code according to the error message.
This message means that you accidentally misspelled a condition for the
SKIP instruction. Check the table of valid conditions and correct your
code to use a valid condition.
This simply means that your game is larger than the available memory on the Chip-8. Unfortunately, the only fix for this is to rewrite your game to generate a smaller binary. Instructions for this are beyond the scope of this document and may be found online.
The Chip-8 processor has sixteen general-purpose registers, numbered from
VF. Each of these registers can hold one byte, and can be
manipulated at will. However, register
VF is used by multiple
instructions as a flag register, and should only be used for that purpose.
The Chip-8 also has one "index" register, denoted by
I. Its main use
is addressing memory for data storage and sprite drawing operations. It
can hold a value ranging from 0 to 4095 inclusive.
The Chip-8 also has 4096 (0x1000) bytes of memory. Out of these, addresses 0x050 through 0x0A0 are reserved for the built-in character set, and binaries are loaded into memory starting at address 0x200. All other addresses are free for use by your games.
The Chip-8 also has two onboard timing devices, called the delay timer and the sound timer. Both can be set through code, and will count down to 0 at 60Hz when set to a non-zero value. The delay timer can be read from, whereas the sound timer cannot. While the sound timer is nonzero, a tone will be played.
ch8asm's assembly language has four major data types. They are:
- Decimal literals (preceded by a
- Hexadecimal literals (preceded by a
- Binary literals (preceded by a
- Labels (preceded by a
Decimal and hexadecimal literals can be any value from 0 to 4095 inclusive, while binary literals may only be one byte long. One use for binary literals is to use them to draw out your sprites. Arrange your binary literals so the 1s represent the desired on-pixels of your sprite, attach them to a label definition, and you can use that label elsewhere in your code to represent your sprite.
Labels come in two varieties: definitions and references. Definitions
ch8asm with a name for a given position in your game's code,
while references allow definitions to be used in code to reference that
position. Definitions are always followed by a colon, while references
are never followed by a colon.
This example snippet draws a smiley face in the upper left-hand corner of the screen:
;this is a definition _spr: %00000000 %01000010 %00000000 %01000010 %00100100 %00011000 mov I, _spr ;this is a reference mov V0, #0 mov V1, #0 draw V0, V1, #6
As a side note, you can comment your code by using a semicolon. Comments start after a semicolon and continue to the end of the line.
Here is a list of all instructions that
ch8asm understands. All
instructions and registers are case-insensitive, and commas must be
inserted between arguments. In this documentation, general purpose
registers are indicated by
VY, the index register is indicated
I, constant values are denoted by
NNN, depending on
the size of the constant, and labels are denoted by
the actual name of the label.
- CLS - Clears the screen.
- DRAW VX, VY, H - Draws a sprite at the coordinates (VX, VY)
with a height of H pixels. The sprite is read bit-coded from memory
starting at the memory location pointed to by
I. To facilitate collision detection,
VFis set to 1 if any pixels were flipped from on to off and to 0 otherwise.
- SCH VX - Sets
Ito point to the hex character corresponding to the value of VX, which must be within the range of 0 to 15, inclusive.
- JMP _lbl - Causes program flow to unconditionally jump to _lbl
- CALL _lbl - Calls a subroutine at _lbl.
- RET - Returns control from a subroutine to its calling code
- SKIP.condition args - Skips the next instruction if condition is true for args. See the table below for a list of valid conditions.
- JPC (_lbl or NNN) - Unconditionally jumps to the argument plus
||Arguments are equal|
||Arguments are not equal|
- MOV dest, src - Stores the value of src in dest. If dest refers
Iregister, then src must be a constant or a label. src cannot be the
- ADD dest, (VX or NN) - Adds the second argument to the first
and stores the result in the first. If the second argument is a constant,
dest cannot be the
Iregister. Furthermore, if an overflow occurs when adding, register
VFis set to 1. If no overflow occurs, then
VFwill be set to 0.
- OR VX, VY - Sets VX to itself bitwise ORed with VY.
- AND VX, VY - Sets VX to itself bitwise ANDed with VY.
- XOR VX, VY - Sets VX to itself bitwise XORed with VY.
- SUB VX, VY - Sets VX to itself minus VY.
VFis set to 0 when a borrow occurs and 1 otherwise.
- SUBN VX, VY - Sets VX to VY minus VX.
VFis set to 0 when a borrow occurs and 1 otherwise.
- SHR VX - Stores the least significant bit of VX in
VFand bitwise shifts VX to the right by 1.
- SHL VX - Stores the most significant bit of VX in
VFand bitwise shifts VX to the left by 1.
- RAND VX, NN - Stores a random byte bitwise ANDed with NN in VX.
- GDL VX - Stores the current value of the delay timer in VX.
- KEY VX - Stops execution until a key is pressed and stores it in VX.
- SDL VX - Sets the delay timer to VX.
- SND VX - Sets the sound timer to VX
- BCD VX - Stores the binary-coded decimal representation of VX in
memory starting at location
- RDP VX - Stores the values of registers
V0through VX in memory starting at location
- RLD VX - Reads data from memory starting at location
You may wish to read the Wikipedia page on the Chip-8 to obtain further information about the processor and its capabilities.
ch8asm is licensed under the GNU General Public License, version 3.
Feedback and suggestions are always appreciated, so if you have an idea,
just open a pull request or issue on GitHub. Thanks for using
and happy programming!