ft: initial disasm of example data

This only contains two instructions of which I know
the correct output.
This commit is contained in:
2025-05-07 15:48:44 +09:00
commit 2af4578c8b
8 changed files with 804 additions and 0 deletions

183
src/instructions.rs Normal file
View 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"),
}
}
}