ft: initial disasm of example data
This only contains two instructions of which I know the correct output.
This commit is contained in:
183
src/instructions.rs
Normal file
183
src/instructions.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
use core::fmt;
|
||||
|
||||
pub type MemAddress = u8;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
/// A single 'line' of executable ASM is called a MetaInstruction, which
|
||||
/// contains the `Instruction`, which will be executed, alongside some Meta
|
||||
/// Informations.
|
||||
pub struct MetaInstruction {
|
||||
pub start: usize, // location of the instruction start
|
||||
pub size: usize, // size of the instruction in bytes
|
||||
pub raw: Vec<u8>, // raw value of instruction
|
||||
pub instruction: Instruction, // actual instruction
|
||||
}
|
||||
|
||||
impl MetaInstruction {
|
||||
pub fn new() -> Self {
|
||||
MetaInstruction {
|
||||
start: 0,
|
||||
size: 0,
|
||||
raw: Vec::new(),
|
||||
instruction: Instruction::NOP(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse n bytes from text section and advance offet.
|
||||
/// Used to get the operands.
|
||||
pub fn take_n_bytes(&mut self, size: usize, offset: &mut usize, text: &Vec<u8>) {
|
||||
self.size = size;
|
||||
self.raw = text[*offset as usize..]
|
||||
.iter()
|
||||
.take(size)
|
||||
.cloned()
|
||||
.collect();
|
||||
*offset += size;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MetaInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:04x}: ", self.start).unwrap();
|
||||
for b in self.raw.iter() {
|
||||
write!(f, "{:02x}", b).unwrap();
|
||||
}
|
||||
write!(f, "\t{}", self.instruction)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
pub enum Instruction {
|
||||
NOP(),
|
||||
// ADD
|
||||
ADD_RM(Register, Memory),
|
||||
ADD_MR(Memory, Register),
|
||||
ADD_RR(Register, Register),
|
||||
ADD_MI(Memory, ImmediateByte),
|
||||
ADD_RI(Register, ImmediateByte),
|
||||
// MOV
|
||||
MOV_RM(Register, Memory),
|
||||
MOV_MR(Memory, Register),
|
||||
MOV_RR(Register, Register),
|
||||
MOV_MI(Memory, ImmediateByte),
|
||||
MOV_RI(Register, ImmediateWord),
|
||||
MOV_SM(SRegister, Memory),
|
||||
MOV_MS(Memory, SRegister),
|
||||
MOV_RS(Register, SRegister),
|
||||
MOV_SR(SRegister, Register),
|
||||
// INT
|
||||
INT(ImmediateByte),
|
||||
}
|
||||
|
||||
impl fmt::Display for Instruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::INT(byte) => write!(f, "INT, {:x}", byte),
|
||||
Self::MOV_RI(reg, word) => write!(f, "MOV {}, {:04x}", reg, word),
|
||||
_ => write!(f, "display not yet implemented"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Types for operand encoding
|
||||
#[derive(Debug)]
|
||||
pub struct Memory(pub MemAddress);
|
||||
#[derive(Debug)]
|
||||
pub struct ImmediateByte(pub u8);
|
||||
#[derive(Debug)]
|
||||
pub struct ImmediateWord(pub u16);
|
||||
|
||||
// ... and the displays for all of them
|
||||
impl fmt::Display for Memory {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ImmediateByte {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
impl fmt::LowerHex for ImmediateByte {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::LowerHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ImmediateWord {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
impl fmt::LowerHex for ImmediateWord {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::LowerHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers of a 8086 processor
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Register {
|
||||
AX,
|
||||
BX,
|
||||
CX,
|
||||
DX,
|
||||
AH,
|
||||
AL,
|
||||
BL,
|
||||
BH,
|
||||
CH,
|
||||
CL,
|
||||
DH,
|
||||
DL,
|
||||
DI,
|
||||
SI,
|
||||
BP,
|
||||
SP,
|
||||
}
|
||||
|
||||
impl fmt::Display for Register {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::AX => write!(f, "AX"),
|
||||
Self::BX => write!(f, "BX"),
|
||||
Self::CX => write!(f, "CX"),
|
||||
Self::DX => write!(f, "DX"),
|
||||
Self::AH => write!(f, "AH"),
|
||||
Self::AL => write!(f, "AL"),
|
||||
Self::BL => write!(f, "BL"),
|
||||
Self::BH => write!(f, "BH"),
|
||||
Self::CH => write!(f, "CH"),
|
||||
Self::CL => write!(f, "CL"),
|
||||
Self::DH => write!(f, "DH"),
|
||||
Self::DL => write!(f, "DL"),
|
||||
Self::DI => write!(f, "DI"),
|
||||
Self::SI => write!(f, "SI"),
|
||||
Self::BP => write!(f, "BP"),
|
||||
Self::SP => write!(f, "SP"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// SRegisters of a 8086 processor
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SRegister {
|
||||
DS,
|
||||
ES,
|
||||
SS,
|
||||
CS,
|
||||
}
|
||||
|
||||
impl fmt::Display for SRegister {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::DS => write!(f, "DS"),
|
||||
Self::ES => write!(f, "ES"),
|
||||
Self::SS => write!(f, "SS"),
|
||||
Self::CS => write!(f, "CS"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user