Crates.io | e8bit_emulator |
lib.rs | e8bit_emulator |
version | |
source | src |
created_at | 2025-05-07 01:18:39.538763+00 |
updated_at | 2025-05-21 17:14:31.977324+00 |
description | 8-bit emulator written in Rust. |
homepage | |
repository | https://github.com/mi66mc/e8bit_emulator |
max_upload_size | |
id | 1663280 |
Cargo.toml error: | TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
This project is a simple 8-bit virtual machine (VM) emulator written in Rust. It simulates a basic CPU with registers, memory, and a set of instructions for performing arithmetic, memory operations, and control flow.
ADD
, SUB
, MUL
, DIV
, MOD
, MULH
MOV
, STORE
[0]
, [A]
, [B]
, etc.JMP
, JZ
, JNZ
, LOOP
INPUT
, PRINT
, PRINTCH
HALT
DRAW
, CLS
, RENDER
CMP
RAND
false
(non-zero) or true
(zero), enabling conditional logic.//
) and instruction separation via ;
or by lines.MOV A 'p'
. Characters are internally treated as their ASCII numeric values and must fit within 8 bits (0–255), just like any other number.80
by 25
virtual screen and rendering it to the console.JMP
, JZ
, JNZ
, LOOP
) instead of numeric instruction indices.You can define a label by writing it at the start of a line followed by a colon, e.g. LOOP_START:
.
You can then use the label name as the target for JMP
, JZ
, JNZ
, or LOOP
instructions:
MOV A 0
MOV B 10
LOOP_START:
ADD A 1
PRINT A
CMP A B
JNZ LOOP_START
HALT
This is equivalent to using numeric indices, but is easier to read and maintain.
The files game.e8
, game2.e8
, example.e8
, example2.e8
, example3.e8
, example4.e8
, example5.e8
, example6.e8
, example7.e8
, and others contain example programs that demonstrate the use of registers, arithmetic operations, memory storage, loops, and conditional logic.
Even or Odd Example:
// EVEN OR ODD
INPUT A // get number from user input
MOD A 2 // get remainder of A divided by 2
CMP A 0 // compare A with 0, if true, zero flag set to true
JZ EVEN // EVEN (jump to label EVEN if zero)
MOV C 'O' // ODD
PRINTCH C -N
MOV C 'D'
PRINTCH C -N
PRINTCH C -N
JMP END
EVEN:
MOV C 'E' // EVEN
PRINTCH C -N
MOV C 'V'
PRINTCH C -N
MOV C 'E'
PRINTCH C -N
MOV C 'N'
PRINTCH C -N
END:
HALT // end program
Factorial Example (example.e8
):
// FACTORIAL SCRIPT
// registers
MOV A 1; // A = 1 (result)
MOV B 5; // B = 5 (number to get factorial)
LOOP_START:
MUL A B; // A *= B
SUB B 1; // B -= 1
LOOP LOOP_START B; // if B != 0 go to LOOP_START
// END
PRINT A; // shows result
HALT;
Install Rust: Ensure you have Rust installed. You can download it from rust-lang.org.
Compile the Program:
cargo build --release
Run the Emulator:
cargo run example.e8 -d
Replace example.e8
with the path to your program file.
If no file is specified, it will run in IDLE mode, where you can enter instructions directly.
The -d
flag is optional and enables debug mode, which provides additional output for debugging purposes.
Programs for the emulator are written in a custom assembly-like language. Each instruction is written on a new line or separated by a semicolon and can include comments starting with //
. Refer to the example programs above for syntax.
Instruction | Description |
---|---|
MOV A 10 |
Move value 10 into register A |
MOV A 'p' |
Move character literal 'p' into register A (ASCII value) |
MOV A [0] |
Move value from memory address 0 into A |
MOV A [B] |
Move value from memory at index stored in B |
ADD A B |
A = A + B |
SUB A 1 |
A = A - 1 |
MUL A 2 |
A = A * 2 |
DIV A 2 |
A = A / 2 |
MOD A 2 |
A = A % 2 (remainder after division) |
MULH A B C |
A = high byte of (B * C) |
STORE A [0] |
Store A into memory[0] |
STORE A [B] |
Store A into memory at index in B |
INPUT A |
Read input (u8 or char) into register A |
INKEY A |
Reads a single key press (non-blocking), stores ASCII code of the key in register A, or 0 if no key was pressed. Only character keys are returned. |
JMP 10 / JMP LABEL |
Jump to instruction index 10 or to label LABEL |
JZ 5 / JZ LABEL |
Jump to index 5 or label if last result was 0 (zero flag set) |
JNZ 8 / JNZ LABEL |
Jump if last result was not zero (zero flag not set) |
LOOP 3 C / LOOP LABEL C |
Jump to index 3 or label while C != 0 |
PRINT A |
Print value of A with newline |
PRINT A -N |
Print value of A without newline |
PRINTCH A |
Print character represented by value in A |
PRINTCH A -N |
Print character without newline |
DRAW X Y C |
Draw character C at screen position (X, Y) |
CLS |
Clear the screen |
CTS |
Clear the terminal screen |
RENDER |
Render the screen to the console (80x25) |
SLP 1000 |
Pause execution for 1 second (1000 ms) |
HALT |
Stops program execution |
CMP A 10 |
Compare register A with value 10. Sets the zero flag if equal. |
RAND A |
Set register A to a random value between 0–255 |
Type | Example | Description |
---|---|---|
Register | A , B , C , D , E |
One of the five registers |
Immediate Value | 42 , 'p' |
A literal number or character between 0–255 |
Memory Address | [0] |
Direct access to memory index 0 |
Memory via Reg | [A] |
Access memory using value in register A |
Note: Square brackets (
[]
) are used to specify memory addresses. For example:
MOV A [0]
loads the value from memory address 0 into register A.STORE A [0]
stores the value of register A into memory address 0.
Instruction | Arg 1 Type | Arg 2 Type | Arg 3 Type |
---|---|---|---|
MOV |
Register | Immediate Value, Register, or Memory Address ([0] , [A] , etc.) |
- |
ADD |
Register | Immediate Value, Register, or Memory Address | - |
SUB |
Register | Immediate Value, Register, or Memory Address | - |
MUL |
Register | Immediate Value, Register, or Memory Address | - |
DIV |
Register | Immediate Value, Register, or Memory Address | - |
MOD |
Register | Immediate Value, Register, or Memory Address | - |
MULH |
Register | Register | Register |
STORE |
Register | Memory Address ([0] , [B] , etc.) |
- |
JMP |
Immediate Value | - | - |
JZ |
Immediate Value | - | - |
JNZ |
Immediate Value | - | - |
LOOP |
Immediate Value (Instruction Index) | Register | - |
PRINT |
Register | Optional: -N to suppress newline |
- |
PRINTCH |
Register | Optional: -N to suppress newline |
- |
INPUT |
Register | - | - |
DRAW |
Immediate Value, Register, or Memory Address | Immediate Value, Register, or Memory Address | Immediate Value, Register, or Memory Address |
CLS |
- | - | - |
CTS |
- | - | - |
RENDER |
- | - | - |
SLP |
Milliseconds | - | - |
HALT |
- | - | - |
CMP |
Register | Immediate Value, Register, or Memory Address | - |
RAND |
Register | - | - |
CTS
instruction to clear the terminal screen and CLS
to clear virtual screen.MOD
instruction to easily check for even/odd numbers or perform modular arithmetic.CMP
instruction is useful for conditional branching with JZ
and JNZ
.PRINTCH
for ASCII output and PRINT
for numeric output.DRAW
, CLS
, and RENDER
for simple graphics.This project is open-source and available under the MIT License.
INKEY
INKEY A
reads a single key press (non-blocking) and stores the ASCII code of the pressed key in register A
.A
is set to 0
.A == 0
).