This project is a two-pass assembler and simulator. It reads assembly code from a text file, processes it, converts it into machine code, and simulates its execution.
It is designed for educational purposes to demonstrate how assemblers and simple CPUs work.
- C compiler (GCC recommended)
- Basic understanding of command-line usage
├── src
│ ├── emulator
│ │ ├── handle_instruction.c
│ │ ├── handle_instruction.h
│ │ ├── main.c
│ │ ├── memory.c
│ │ ├── memory.h
│ │ └── opcode_table.h
│ ├── parser
│ │ ├── isa.c
│ │ ├── isa.h
│ │ ├── lexer.c
│ │ ├── lexer.h
│ │ ├── main.c
│ │ ├── parser.c
│ │ ├── parser.h
│ │ ├── symbol.c
│ │ ├── symbol.h
│ │ └── token.h
│ ├── error.c
│ ├── error.h
│ ├── instruction.c
│ ├── instruction.h
│ ├── main.c
│ ├── main.h
│ └── type.h
└── Makefile
| Opcode | Instruction | Description |
|---|---|---|
| 0 | or rd, rn, S |
Bitwise OR between rn and S, stored in rd |
| 1 | and rd, rn, S |
Bitwise AND between rn and S, stored in rd |
| 2 | xor rd, rn, S |
Bitwise XOR between rn and S, stored in rd |
| 3 | add rd, rn, S |
Adds rn and S, stored in rd |
| 4 | sub rd, rn, S |
Subtracts S from rn, stored in rd |
| 5 | mul rd, rn, S |
Multiplies lower 16 bits of rn and S, stored in rd |
| 6 | div rd, rn, S |
Integer division of rn by S, stored in rd |
| 7 | shr rd, rn, S |
Shifts rn right by S bits (left if S < 0) |
| 12 | ldb rd, (rn)S |
Load 1 byte from memory at rn + S into rd |
| 13 | ldh rd, (rn)S |
Load 2 bytes from memory at rn + S into rd |
| 14 | ldw rd, (rn)S |
Load 4 bytes from memory at rn + S into rd |
| 15 | stb (rd)S, rn |
Store 1 byte from rn into memory at rd + S |
| 16 | sth (rd)S, rn |
Store 2 bytes from rn into memory at rd + S |
| 17 | stw (rd)S, rn |
Store 4 bytes from rn into memory at rd + S |
| 21 | jmp S |
Unconditional jump to address S |
| 22 | jzs S |
Jump to S if Zero flag is set |
| 23 | jzc S |
Jump to S if Zero flag is clear |
| 24 | jcs S |
Jump to S if Carry flag is set |
| 25 | jcc S |
Jump to S if Carry flag is clear |
| 26 | jns S |
Jump to S if Negative flag is set |
| 27 | jnc S |
Jump to S if Negative flag is clear |
| 28 | in rd |
Reads an integer from input and stores it in rd |
| 29 | out rd |
Outputs the decimal value of rd |
| 30 | rnd rd, rn, S |
Random integer in [rn, S-1] stored in rd |
| 31 | hlt |
Stops program execution |
-
For all instructions except jumps,
Scan be:- A register
- An immediate value
-
For jump instructions,
Scan be:- A register
- An immediate value
- A label
- Labels are identifiers followed by a colon (
:) - Must start with a letter or underscore
- Can contain letters, digits, and underscores
main:
_loop1:- Registers are named
r0throughr31 - Case-insensitive (
r0orR0) - Valid range: 0–31
- Decimal:
#42 - Hexadecimal:
#h2A
- Tokens can be separated by spaces, tabs, or commas
- Parentheses
()are used for memory addressing - Colon
:is used for labels - Comments are not supported in this version
- Each instruction must be on its own line
The following program reads a value from input, increments it by 1, and outputs the result:
main:
in r1
add r1, r1, #1
out r1
hltNote: Comments are shown here for explanation but are not supported by the assembler.
Save this program in a file, for example: example.txt.
make./simulator example.txt