Implemented more of the assembler

This commit is contained in:
Anthony Foxclaw 2020-02-07 22:33:36 -05:00
parent 4bfde58cc5
commit fe69c0d0c8
4 changed files with 68 additions and 4 deletions

View file

@ -7,7 +7,7 @@ pub mod register_parser;
use crate::instruction::Opcode;
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum Token {
Opcode { code: Opcode },
Register { reg_num: u8 },

View file

@ -5,7 +5,6 @@ use crate::assembler::operand_parser::integer_operand;
use crate::assembler::register_parser::register;
use nom::types::CompleteStr;
use nom::*;
#[derive(Debug, PartialEq)]
pub struct AssemblerInstruction {
@ -15,6 +14,53 @@ pub struct AssemblerInstruction {
op3: Option<Token>,
}
impl AssemblerInstruction {
pub fn to_bytes(&self) -> Vec<u8> {
let mut results = vec![];
match self.opcode.clone() {
Token::Opcode { code } => match code {
_ => {
results.push(code as u8);
}
},
_ => {
println!("Incorrect opcode!");
std::process::exit(0);
}
};
for operand in vec![&self.op1, &self.op2, &self.op3] {
match operand {
Some(t) => AssemblerInstruction::extract_operand(t, &mut results),
None => {}
}
}
results
}
fn extract_operand(t: &Token, results: &mut Vec<u8>) {
match t {
Token::Register { reg_num } => {
results.push(*reg_num);
},
Token::Number { value } => {
let conv = *value as u16;
let byte1 = conv;
let byte2 = conv >> 8;
results.push(byte2 as u8);
results.push(byte1 as u8);
},
_ => {
println!("Opcode found in operand field");
std::process::exit(1);
}
}
}
}
named!(pub instruction_one<CompleteStr, AssemblerInstruction>,
do_parse!(
o: opcode_load >>

View file

@ -8,6 +8,16 @@ pub struct Program {
instructions: Vec<AssemblerInstruction>,
}
impl Program {
pub fn to_bytes(&self) -> Vec<u8> {
let mut prog = vec![];
for instruction in &self.instructions {
prog.append(&mut instruction.to_bytes());
}
prog
}
}
named!(pub program<CompleteStr, Program>,
do_parse!(
instructions: many1!(instruction_one) >>
@ -22,7 +32,6 @@ named!(pub program<CompleteStr, Program>,
#[cfg(test)]
mod instruction_parser_test {
use super::*;
use crate::instruction::Opcode;
#[test]
fn test_parse_instruction() {
@ -31,4 +40,13 @@ mod instruction_parser_test {
assert_eq!(leftover, CompleteStr(""));
assert_eq!(1, p.instructions.len());
}
#[test]
fn test_program_to_bytes() {
let result = program(CompleteStr("load $0 #100\n"));
let (_, prog) = result.unwrap();
let bytecode = prog.to_bytes();
assert_eq!(bytecode.len(), 4);
println!("{:?}", bytecode);
}
}

View file

@ -1,6 +1,6 @@
#![allow(dead_code)]
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum Opcode {
HLT,
IGL,