diff --git a/src/disasm.rs b/src/disasm.rs index 0188799..b084e34 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -2,7 +2,8 @@ use core::fmt; use std::{fs::File, io::Read, process::exit}; use crate::aout::Aout; -use crate::instructions::{Displacement, MemoryIndex}; +use crate::instructions::{Displacement, MemoryIndex, RegisterId, SegmentRegister}; +use crate::modrm; use crate::{ Args, instructions::{ImmediateByte, ImmediateWord, Instruction, Opcode, Register}, @@ -99,7 +100,7 @@ impl Disassembler { /// Parse a single modrm byte, return the resulting MemoryIndex and advance the offset. /// Returns the parsed modrm memory access and the source register - pub fn parse_modrm_byte_to_memindex(&mut self) -> (MemoryIndex, Register) { + pub fn parse_modrm_byte(&mut self) -> (MemoryIndex, RegisterId) { // advance to operand self.offset += 1; let modrm = self.text[self.offset]; @@ -109,7 +110,7 @@ impl Disassembler { // Calculate ModRM byte with bitmask let modulo = modrm >> 6; - let reg = (modrm >> 3) & 7; + let reg_id = (modrm >> 3) & 7; let rm = modrm & 7; let displacement = match modulo { @@ -183,7 +184,7 @@ impl Disassembler { _ => panic!("Invalid ModRM byte encountered"), }; - (index, Register::by_id(reg)) + (index, reg_id) } /// Decode instructions from the text section of the provided binary @@ -205,14 +206,23 @@ impl Disassembler { self.instruction.raw.push(opcode); self.instruction.opcode = match opcode { // ADD - 0x00 => { - let (idx, reg) = self.parse_modrm_byte_to_memindex(); - Opcode::ADD_EbGb(idx, reg) - } + 0x00 => modrm!(self, ADD_EbGb), + 0x01 => modrm!(self, ADD_EvGv), + 0x02 => modrm!(self, ADD_GbEb), + 0x03 => modrm!(self, ADD_GvEv), + 0x04 => Opcode::ADD_ALIb(ImmediateByte(self.parse_byte())), + 0x05 => Opcode::ADD_AXIv(ImmediateWord(self.parse_word())), + // PUSH + 0x06 => Opcode::PUSH(SegmentRegister::by_id(self.parse_modrm_byte().1)), + // POP + 0x07 => Opcode::POP(SegmentRegister::by_id(self.parse_modrm_byte().1)), + // OR + 0x08 => modrm!(self, OR_EbGb), + 0x0A => modrm!(self, OR_GbEb), // INT 0xCD => Opcode::INT(ImmediateByte(self.parse_byte())), // MOV - 0xBB => Opcode::MOV_BXIv(Register::BX, ImmediateWord(self.parse_word())), + 0xBB => Opcode::MOV_BXIv(ImmediateWord(self.parse_word())), _ => { eprintln!( "Encountered unknown self.instructionuction '0x{:x}'", diff --git a/src/disasm_macros.rs b/src/disasm_macros.rs new file mode 100644 index 0000000..61d6d1e --- /dev/null +++ b/src/disasm_macros.rs @@ -0,0 +1,8 @@ +#[macro_export] +/// Generate an Opcode for 'normal' ModRM instructions with mem access and a reg +macro_rules! modrm { + ($self:ident, $variant:ident) => {{ + let (idx, reg) = $self.parse_modrm_byte(); + Opcode::$variant(idx, Register::by_id(reg)) + }}; +} diff --git a/src/instructions.rs b/src/instructions.rs index 882d4b0..ad6e358 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -43,10 +43,22 @@ pub enum Opcode { NOP(), // ADD ADD_EbGb(MemoryIndex, Register), - // MOV - MOV_BXIv(Register, ImmediateWord), + ADD_EvGv(MemoryIndex, Register), + ADD_GbEb(MemoryIndex, Register), + ADD_GvEv(MemoryIndex, Register), + ADD_ALIb(ImmediateByte), + ADD_AXIv(ImmediateWord), + // PUSH + PUSH(SegmentRegister), + // POP + POP(SegmentRegister), + // OR + OR_EbGb(MemoryIndex, Register), + OR_GbEb(MemoryIndex, Register), // INT INT(ImmediateByte), + // MOV + MOV_BXIv(ImmediateWord), } impl fmt::Display for Opcode { @@ -54,7 +66,8 @@ impl fmt::Display for Opcode { match self { Self::INT(byte) => write!(f, "INT, {:x}", byte), Self::ADD_EbGb(mem, reg) => write!(f, "ADD {}, {}", mem, reg), - Self::MOV_BXIv(reg, word) => write!(f, "MOV {}, {:04x}", reg, word), + Self::ADD_GbEb(mem, reg) => write!(f, "ADD {}, {}", reg, mem), + Self::MOV_BXIv(word) => write!(f, "MOV BX, {:04x}", word), _ => write!(f, "display not yet implemented"), } } @@ -83,10 +96,13 @@ pub enum Register { SP, } +/// Selector for Register or Segment Register +pub type RegisterId = u8; + #[allow(dead_code)] impl Register { /// Find the register corresponding to the 8086 bytecode ID - pub fn by_id(id: u8) -> Self { + pub fn by_id(id: RegisterId) -> Self { match id { 0x00 => Self::AL, 0x01 => Self::CL, @@ -133,7 +149,7 @@ impl fmt::Display for Register { } /// Segment Registers of a 8086 processor -#[derive(Debug)] +#[derive(Debug, Clone)] #[allow(dead_code)] pub enum SegmentRegister { DS, @@ -213,13 +229,13 @@ impl fmt::Display for MemoryIndex { }, None => match &self.displacement { Some(displacement) => write!(f, "[{}+{}]", base, displacement), - None => write!(f, "[{}]", base), + None => write!(f, "{}", base), }, }, None => match &self.index { Some(index) => match &self.displacement { Some(displacement) => write!(f, "{}+{}", index, displacement), - None => write!(f, "[{}]", index), + None => write!(f, "{}", index), }, None => panic!("Invalid MemoryIndex encountered"), }, diff --git a/src/main.rs b/src/main.rs index 4170fb3..d9bc7a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use clap::{Parser, Subcommand}; mod aout; mod disasm; +mod disasm_macros; mod instructions; #[derive(Subcommand, Debug)]