Krolyxon
Commit debe2ec

Branches

Tags

Refs →

bench51debe2ec

add simple assembler

Author
krolxon
Date
2026-01-04 23:49 +0530
Parent
a566c17
Commit
debe2ecbc4f819dfec7f5ca7c1f0e2fd6bc37708

+107 −48

4 files changed

  1. R code.asm → program.asm +0 −0
  2. A src/assembler.rs +73 −0
  3. M src/cpu.rs +24 −6
  4. M src/main.rs +10 −42
R code.asm → program.asm View

[No content changes]

A src/assembler.rs View
@@ -0,0 +1,73 @@
1+use crate::instructions::Instruction;
2+
3+fn tokenize(line: &str) -> Vec<String> {
4+ line.split(|c| c == ' ' || c == ',' || c == '\t')
5+ .filter(|s| !s.is_empty())
6+ .map(|s| s.to_lowercase())
7+ .collect()
8+}
9+
10+fn parse_reg(s: &str) -> u8 {
11+ match s {
12+ "a" => 0,
13+ "b" => 1,
14+ "c" => 2,
15+ "d" => 3,
16+ _ => panic!("Unknown register {}", s),
17+ }
18+}
19+
20+pub fn assembler(source: &str) -> Vec<u8> {
21+ let mut bytes = Vec::new();
22+
23+ for (line_no, line) in source.lines().enumerate() {
24+ let line = line.trim();
25+
26+ // Comments in assembly start with ";"
27+ if line.is_empty() || line.starts_with(';') {
28+ continue;
29+ }
30+
31+ let tokens = tokenize(line);
32+
33+ match tokens[0].as_str() {
34+ "mov" => {
35+ // mov reg, imm
36+ let reg = parse_reg(&tokens[1]);
37+ let imm: u8 = tokens[2].parse().unwrap();
38+
39+ bytes.push(Instruction::MOV as u8);
40+ bytes.push(reg);
41+ bytes.push(imm);
42+ }
43+
44+ "add" => {
45+ // add a, b
46+ let r1 = parse_reg(&tokens[1]);
47+ let r2 = parse_reg(&tokens[2]);
48+
49+ bytes.push(Instruction::ADD as u8);
50+ bytes.push(r1);
51+ bytes.push(r2);
52+ }
53+
54+ "sub" => {
55+ // sub a, b
56+ let r1 = parse_reg(&tokens[1]);
57+ let r2 = parse_reg(&tokens[2]);
58+
59+ bytes.push(Instruction::SUB as u8);
60+ bytes.push(r1);
61+ bytes.push(r2);
62+ }
63+
64+ "hlt" => {
65+ bytes.push(Instruction::HLT as u8);
66+ }
67+
68+ _ => panic!("Line {}: unknown instruction", line_no + 1),
69+ }
70+ }
71+
72+ bytes
73+}
M src/cpu.rs View
@@ -1,4 +1,6 @@
1+use crate::instructions::Instruction;
12 use crate::memory::Memory;
3+
24 #[derive(Default, Debug)]
35 pub struct CPU {
46 pub a: u8,
@@ -16,6 +18,22 @@ pub struct CPU {
1618 }
1719
1820 impl CPU {
21+ pub fn step(&mut self, mem: &mut Memory) {
22+ let opcode = mem.read(self.pc);
23+ self.inc_pc();
24+
25+ match opcode {
26+ x if x == Instruction::MOV as u8 => self.mov(mem),
27+ x if x == Instruction::ADD as u8 => self.add(mem),
28+ x if x == Instruction::SUB as u8 => self.sub(mem),
29+ x if x == Instruction::JMP as u8 => self.jmp(mem),
30+ x if x == Instruction::JZ as u8 => self.jz(mem),
31+ x if x == Instruction::JNZ as u8 => self.jnz(mem),
32+ x if x == Instruction::HLT as u8 => self.halt(),
33+ _ => panic!("Unknown opcode {:02X}", opcode),
34+ }
35+ }
36+
1937 pub fn inc_pc(&mut self) {
2038 self.pc += 1;
2139 }
@@ -24,7 +42,7 @@ impl CPU {
2442 self.halted = true;
2543 }
2644
27− pub fn mov(&mut self, mem: &mut Memory) {
45+ pub fn mov(&mut self, mem: &Memory) {
2846 let reg = mem.read(self.pc);
2947 self.inc_pc();
3048 let val = mem.read(self.pc);
@@ -41,7 +59,7 @@ impl CPU {
4159 self.zero = val == 0;
4260 }
4361
44− pub fn add(&mut self, mem: &mut Memory) {
62+ pub fn add(&mut self, mem: &Memory) {
4563 let dest = mem.read(self.pc);
4664 self.pc += 1;
4765 let src = mem.read(self.pc);
@@ -83,7 +101,7 @@ impl CPU {
83101 self.carry = carry;
84102 }
85103
86− pub fn sub(&mut self, mem: &mut Memory) {
104+ pub fn sub(&mut self, mem: &Memory) {
87105 let dest = mem.read(self.pc);
88106 self.pc += 1;
89107 let src = mem.read(self.pc);
@@ -125,7 +143,7 @@ impl CPU {
125143 self.carry = borrow;
126144 }
127145
128− pub fn jmp(&mut self, mem: &mut Memory) {
146+ pub fn jmp(&mut self, mem: &Memory) {
129147 let low = mem.read(self.pc) as u16;
130148 self.inc_pc();
131149 let high = mem.read(self.pc) as u16;
@@ -136,7 +154,7 @@ impl CPU {
136154 self.pc = addrs;
137155 }
138156
139− pub fn jz(&mut self, mem: &mut Memory) {
157+ pub fn jz(&mut self, mem: &Memory) {
140158 let low = mem.read(self.pc) as u16;
141159 self.inc_pc();
142160 let high = mem.read(self.pc) as u16;
@@ -149,7 +167,7 @@ impl CPU {
149167 }
150168 }
151169
152− pub fn jnz(&mut self, mem: &mut Memory) {
170+ pub fn jnz(&mut self, mem: &Memory) {
153171 let low = mem.read(self.pc) as u16;
154172 self.inc_pc();
155173 let high = mem.read(self.pc) as u16;
M src/main.rs View
@@ -1,58 +1,26 @@
1+mod assembler;
12 mod cpu;
23 mod instructions;
34 mod memory;
45
56 use cpu::CPU;
6−use instructions::Instruction;
77 use memory::Memory;
88
9+use crate::assembler::assembler;
10+
911 fn main() {
1012 let mut cpu = CPU::default();
1113 let mut mem = Memory::new();
1214
13− // a = 10
14− mem.write(0x0000, Instruction::MOV as u8);
15− mem.write(0x0001, 0);
16− mem.write(0x0002, 5);
17−
18− // b = 2
19− mem.write(0x0003, Instruction::MOV as u8);
20− mem.write(0x0004, 1);
21− mem.write(0x0005, 3);
22−
23− // a = a + b
24− mem.write(0x0006, Instruction::SUB as u8);
25− mem.write(0x0007, 0);
26− mem.write(0x0008, 1);
27−
28− // JMP to halt
29− mem.write(0x0009, Instruction::JNZ as u8);
30− mem.write(0x000a, 0x0f); // Low
31− mem.write(0x000b, 0x00); // High
15+ let asm = std::fs::read_to_string("program.asm").unwrap();
16+ let program = assembler(&asm);
3217
33− // set b = 0
34− mem.write(0x000c, Instruction::MOV as u8);
35− mem.write(0x000d, 1);
36− mem.write(0x000e, 0);
37−
38− // halt
39− mem.write(0x000f, Instruction::HLT as u8);
18+ for (i, byte) in program.iter().enumerate() {
19+ mem.write(i as u16, *byte);
20+ }
4021
4122 while !cpu.halted {
42− let opcode = mem.read(cpu.pc);
43− cpu.inc_pc();
44−
45− match opcode {
46− x if x == Instruction::MOV as u8 => cpu.mov(&mut mem),
47− x if x == Instruction::ADD as u8 => cpu.add(&mut mem),
48− x if x == Instruction::SUB as u8 => cpu.sub(&mut mem),
49− x if x == Instruction::JMP as u8 => cpu.jmp(&mut mem),
50− x if x == Instruction::JZ as u8 => cpu.jz(&mut mem),
51− x if x == Instruction::JNZ as u8 => cpu.jnz(&mut mem),
52− x if x == Instruction::HLT as u8 => cpu.halt(),
53− _ => panic!("Unknown opcode {:02X}", opcode),
54− }
23+ cpu.step(&mut mem);
24+ println!("{:?}", cpu);
5525 }
56−
57− println!("{:#?}", cpu);
5826 }