From fe69c0d0c84268f547ae54fe36dd982b933b7738 Mon Sep 17 00:00:00 2001 From: Anthony Foxclaw <35226681+tonytins@users.noreply.github.com> Date: Fri, 7 Feb 2020 22:33:36 -0500 Subject: [PATCH] Implemented more of the assembler --- src/assembler.rs | 2 +- src/assembler/instruction_parser.rs | 48 ++++++++++++++++++++++++++++- src/assembler/program_parser.rs | 20 +++++++++++- src/instruction.rs | 2 +- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/assembler.rs b/src/assembler.rs index 087dc0d..67d7908 100644 --- a/src/assembler.rs +++ b/src/assembler.rs @@ -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 }, diff --git a/src/assembler/instruction_parser.rs b/src/assembler/instruction_parser.rs index 9fc9138..100c366 100644 --- a/src/assembler/instruction_parser.rs +++ b/src/assembler/instruction_parser.rs @@ -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, } +impl AssemblerInstruction { + pub fn to_bytes(&self) -> Vec { + 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) { + 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, do_parse!( o: opcode_load >> diff --git a/src/assembler/program_parser.rs b/src/assembler/program_parser.rs index bfdf5eb..c0e8a33 100644 --- a/src/assembler/program_parser.rs +++ b/src/assembler/program_parser.rs @@ -8,6 +8,16 @@ pub struct Program { instructions: Vec, } +impl Program { + pub fn to_bytes(&self) -> Vec { + let mut prog = vec![]; + for instruction in &self.instructions { + prog.append(&mut instruction.to_bytes()); + } + prog + } +} + named!(pub program, do_parse!( instructions: many1!(instruction_one) >> @@ -22,7 +32,6 @@ named!(pub 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); + } } diff --git a/src/instruction.rs b/src/instruction.rs index 0bd5f23..44a24af 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Opcode { HLT, IGL,