add SYS instruction

This commit is contained in:
krolxon 2026-01-08 19:21:43 +05:30
parent 4667df1425
commit 467ec78e89
5 changed files with 71 additions and 20 deletions

View File

@ -20,6 +20,7 @@
| MUL | mul r1, r2 | | MUL | mul r1, r2 |
| DIV | div r1, r2 | | DIV | div r1, r2 |
| CALL | call \<label\> | | CALL | call \<label\> |
| SYS | sys \<syscall_no\> |
| HLT (Halt) | hlt | | HLT (Halt) | hlt |
@ -33,6 +34,7 @@
| PC | 16-bit | Program Counter | | PC | 16-bit | Program Counter |
| SP | 16-bit | Stack pointer | | SP | 16-bit | Stack pointer |
## Flags ## Flags
| Flag | Description | | Flag | Description |
| ----- | ------------ | | ----- | ------------ |
@ -40,6 +42,14 @@
| C | Carry/Borrow | | C | Carry/Borrow |
## Syscalls
| Imm | Meaning |
| --- | ------- |
| 0 | Exit Program |
| 1 | Print register A as integer |
| 2 | Print register A as ASCII char |
# Usage # Usage
```bash ```bash
cargo run -- --f <examples/filename.asc> cargo run -- --f <examples/filename.asc>
@ -49,11 +59,12 @@ cargo run -- --f <examples/filename.asc>
- [x] Assembler - [x] Assembler
- [x] Lexer/Tokenizer - [x] Lexer/Tokenizer
- [x] Add label support (supporting JMP/JZ/JNZ) - [x] Add label support (supporting JMP/JZ/JNZ)
- [ ] Add instructions - [x] Add instructions
- [x] CMP - [x] CMP
- [x] MUL - [x] MUL
- [x] DIV - [x] DIV
- [x] CALL - [x] CALL
- [x] RET - [x] RET
- [ ] Error handling - [x] SYS
- [ ] Build Debugger - [ ] Better Error handling
- [ ] TUI Debugger

7
examples/syscall.asm Normal file
View File

@ -0,0 +1,7 @@
mov a, 72 ; 'H'
sys 2
mov a, 105 ; 'i'
sys 2
mov a, 10 ; '\n'
sys 2
sys 0

View File

@ -26,6 +26,7 @@ fn is_reg(s: &str) -> bool {
fn instr_size(tokens: &[String]) -> u16 { fn instr_size(tokens: &[String]) -> u16 {
match tokens[0].as_str() { match tokens[0].as_str() {
"mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3, "mov" | "add" | "sub" | "jmp" | "jz" | "jnz" | "cmp" | "mul" | "div" | "call" => 3,
"sys" => 2,
"hlt" | "ret" => 1, "hlt" | "ret" => 1,
_ => panic!("Unknown instruction {}", tokens[0]), _ => panic!("Unknown instruction {}", tokens[0]),
} }
@ -190,6 +191,12 @@ pub fn assembler(source: &str) -> Vec<u8> {
bytes.push(Instruction::HLT as u8); bytes.push(Instruction::HLT as u8);
} }
"sys" => {
let imm = tokens[1].parse().unwrap();
bytes.push(Instruction::SYS as u8);
bytes.push(imm);
}
_ => panic!("Line {}: unknown instruction", line_no + 1), _ => panic!("Line {}: unknown instruction", line_no + 1),
} }
} }

View File

@ -69,21 +69,9 @@ impl CPU {
x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem), x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
x if x == Instruction::MUL as u8 => self.mul(mem), x if x == Instruction::MUL as u8 => self.mul(mem),
x if x == Instruction::DIV as u8 => self.div(mem), x if x == Instruction::DIV as u8 => self.div(mem),
x if x == Instruction::CALL as u8 => { x if x == Instruction::CALL as u8 => self.call(mem),
let low = mem.read(self.pc) as u16; self.inc_pc(); x if x == Instruction::RET as u8 => self.ret(mem),
let high = mem.read(self.pc) as u16; self.inc_pc(); x if x == Instruction::SYS as u8 => self.syscall(mem),
let addr = (high << 8) | low;
let return_addr = self.pc;
self.push16(mem, return_addr);
self.pc = addr;
},
x if x == Instruction::RET as u8 => {
let addr = self.pop16(mem);
self.pc = addr;
},
x if x == Instruction::HLT as u8 => self.halt(), x if x == Instruction::HLT as u8 => self.halt(),
_ => panic!("Unknown opcode {:02X}", opcode), _ => panic!("Unknown opcode {:02X}", opcode),
} }
@ -94,12 +82,10 @@ impl CPU {
} }
pub fn inc_sp(&mut self) { pub fn inc_sp(&mut self) {
// self.sp += 1;
self.sp = self.sp.wrapping_add(1); self.sp = self.sp.wrapping_add(1);
} }
pub fn dec_sp(&mut self) { pub fn dec_sp(&mut self) {
// self.sp -= 1;
self.sp = self.sp.wrapping_sub(1); self.sp = self.sp.wrapping_sub(1);
} }
@ -379,6 +365,44 @@ impl CPU {
// carry unchanged // carry unchanged
} }
pub fn call(&mut self, mem: &mut Memory ) {
let low = mem.read(self.pc) as u16; self.inc_pc();
let high = mem.read(self.pc) as u16; self.inc_pc();
let addr = (high << 8) | low;
let return_addr = self.pc;
self.push16(mem, return_addr);
self.pc = addr;
}
pub fn ret(&mut self, mem: &mut Memory) {
let addr = self.pop16(mem);
self.pc = addr;
}
pub fn syscall(&mut self, mem: &Memory) {
let num = mem.read(self.pc);
self.pc = self.pc.wrapping_add(1);
match num {
0 => {
// exit
self.halted = true;
}
1 => {
// print A as number
println!("{}", self.a);
}
2 => {
// print A as ASCII char
print!("{}", self.a as char);
}
_ => panic!("Unknown syscall {}", num),
}
}
fn get_reg(&self, r: u8) -> u8 { fn get_reg(&self, r: u8) -> u8 {
match r { match r {
0 => self.a, 0 => self.a,

View File

@ -16,6 +16,7 @@ pub enum Instruction {
DIV = 0x0D, DIV = 0x0D,
CALL = 0x0E, CALL = 0x0E,
RET = 0x0F, RET = 0x0F,
SYS = 0x10,
HLT = 0xFF, HLT = 0xFF,
} }
@ -33,6 +34,7 @@ impl Instruction {
0x0D => "DIV", 0x0D => "DIV",
0x0E => "CALL", 0x0E => "CALL",
0x0F => "RET", 0x0F => "RET",
0x10 => "SYS",
0xFF => "HLT", 0xFF => "HLT",
_ => "???", _ => "???",