This project is a two-pass assembler written in C.
It translates my own assembly language into machine code that runs on a modified Ben Eater–style TTL CPU.
The assembler handles opcodes, directives, and labels, and outputs a 16-byte machine code image.
- Supports labels, opcodes, and directives (
.org,.word). - Two-pass design:
- First pass resolves labels and addresses.
- Second pass generates final machine code.
- Error reporting shows the filename, line number, and offending source line.
- Produces a 16-byte machine code image (addresses
0x0–0xF). - Written in portable C (no dependencies beyond standard library).
gcc main.c -o assembler./assembler input.asminput.asm→ The assembly source file to compile.
.org 0xf
.word 0x0 ; i
.org 0x0
add_loop:
lda 0xf
out
add #0x1
jc sub_loop
sta 0xf
jmp add_loop
sub_loop:
lda 0xf
out
sub #0x1
jz add_loop
sta 0xf
jmp sub_loop./assembler program.asmSuccessfully compiled!
0000 00011111
0001 11100000
0010 01100001
...
| Mnemonic | Binary Opcode | Notes |
|---|---|---|
lda |
0001 | Load memory to A register |
ldi |
0010 | Load immediate |
sta |
0011 | Store A register to memory |
add |
0100 | Add memory to A register |
sub |
0101 | Subtract memory from A register |
adi |
0110 | Add immediate |
sbi |
0111 | Subtract immediate |
jnz |
1010 | Jump if not zero |
jmp |
1011 | Unconditional jump |
jz |
1100 | Jump if zero |
jc |
1101 | Jump if carry |
out |
1110 | Output A register |
hlt |
1111 | Halt (no operand) |
.org <hex>→ Sets the starting address (0–15)..word <hex>→ Inserts a raw 8-bit value (0–255).- Immediate values use
#(e.g.,lda #5). - Labels must end with
:when defined. - Opcodes without operands:
hlt,out.
- Memory is limited to 16 instructions.
- Immediate/address operands must fit within
0xF. - Only one input file per run.
Made by Gerald Negvesky
For custom Ben Eater TTL CPU build.