From 540555d7a95f75a15f17a71f2f62f788a863ff81 Mon Sep 17 00:00:00 2001 From: Erin Date: Tue, 1 Aug 2023 22:13:22 +0200 Subject: [PATCH] Added magic --- hbasm/src/lib.rs | 28 ++++++++++++++++++++-------- hbbytecode/src/gen_valider.rs | 11 +++++++++++ hbvm/src/lib.rs | 2 +- spec.md | 1 + 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index cf7da9e0..0b301b96 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -1,11 +1,11 @@ //! Holey Bytes Assembler -//! +//! //! Some people claim: //! > Write programs to handle text streams, because that is a universal interface. //! //! We at AbleCorp believe that nice programatic API is nicer than piping some text //! into a program. It's less error-prone and faster. -//! +//! //! So this crate contains both assembleer with API for programs and a text assembler //! for humans to write @@ -15,26 +15,37 @@ extern crate alloc; mod macros; -use {alloc::vec::Vec, hashbrown::HashSet}; +use { + alloc::{vec, vec::Vec}, + hashbrown::HashSet, +}; /// Assembler -/// +/// /// - Opcode-generic, instruction-type-specific methods are named `i_param_` /// - You likely won't need to use them, but they are here, just in case :) /// - Instruction-specific methods are named `i_` -#[derive(Default)] pub struct Assembler { pub buf: Vec, pub sub: HashSet, } +impl Default for Assembler { + fn default() -> Self { + Self { + buf: vec![0; 3], + sub: Default::default(), + } + } +} + hbbytecode::invoke_with_def!(macros::text::gen_text); impl Assembler { hbbytecode::invoke_with_def!(macros::asm::impl_asm); - /// Append 12 zeroes (UN) at the end - /// + /// Append 12 zeroes (UN) at the end and add magic to the begining + /// /// # HoleyBytes lore /// /// In reference HBVM implementation checks are done in @@ -61,11 +72,12 @@ impl Assembler { /// Why 12 bytes? That's the size of largest instruction parameter part. pub fn finalise(&mut self) { self.buf.extend([0; 12]); + self.buf[0..3].copy_from_slice(&[0xAB, 0x1E, 0x0B]); } } /// Immediate value -/// +/// /// # Implementor notice /// It should insert exactly 8 bytes, otherwise output will be malformed. /// This is not checked in any way diff --git a/hbbytecode/src/gen_valider.rs b/hbbytecode/src/gen_valider.rs index 9149650f..c9d9ab73 100644 --- a/hbbytecode/src/gen_valider.rs +++ b/hbbytecode/src/gen_valider.rs @@ -23,6 +23,8 @@ macro_rules! gen_valider { RegisterArrayOverflow, /// Program is not validly terminated InvalidEnd, + /// Program misses magic + MissingMagic } /// Error @@ -37,6 +39,14 @@ macro_rules! gen_valider { /// Perform bytecode validation. If it passes, the program should be /// sound to execute. pub fn validate(mut program: &[u8]) -> Result<(), Error> { + // Validate magic + if program.get(0..3) != Some(&[0xAB, 0x1E, 0x0B]) { + return Err(Error { + kind: ErrorKind::MissingMagic, + index: 0, + }); + } + // Program has to end with 12 zeroes, if there is less than // 12 bytes, program is invalid. if program.len() < 12 { @@ -57,6 +67,7 @@ macro_rules! gen_valider { } let start = program; + program = &program[3..]; loop { use crate::opcode::*; program = match program { diff --git a/hbvm/src/lib.rs b/hbvm/src/lib.rs index 8e07bb55..67b1dda1 100644 --- a/hbvm/src/lib.rs +++ b/hbvm/src/lib.rs @@ -73,7 +73,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize> pfhandler: traph, pc: 0, program_len: program.len() - 12, - program, + program: &program[3..], timer: 0, copier: None, } diff --git a/spec.md b/spec.md index 67094ea2..b5cbcc2d 100644 --- a/spec.md +++ b/spec.md @@ -1,6 +1,7 @@ # HoleyBytes ISA Specification # Bytecode format +- Holey Bytes program should start with following magic: `0xAB1E0B` - All numbers are encoded little-endian - There is 256 registers, they are represented by a byte - Immediate values are 64 bit