ft: implement more mnemonics

This commit is contained in:
2025-05-14 11:28:07 +09:00
parent b5c178ea61
commit 04493b1179
3 changed files with 95 additions and 9 deletions

View File

@@ -8,7 +8,7 @@ use crate::{
Args,
instructions::{Instruction, Mnemonic},
};
use crate::{modrmb, modrmgprb, modrmgprv, modrms, modrmv};
use crate::{modrmb, modrmgpr1b, modrmgpr1v, modrms, modrmv};
#[derive(Debug)]
/// Generic errors, which are encountered during parsing.
@@ -143,7 +143,7 @@ impl Disassembler {
displacement = Some(Operand::Word(self.parse_word()));
}
0b11 => {
log::debug!("ModRM (0b{:b}) to/from Register (0b{:b})", rm, reg);
log::debug!("ModRM ({:#b}) to/from Register ({:#b})", rm, reg);
// XXX: find a nicer way instead of using Byte(0) and Word(0)
let target = match width {
Operand::Byte(_) => ModRmTarget::Register(Register::by_id(Operand::Byte(rm))),
@@ -368,7 +368,7 @@ impl Disassembler {
0x5E => Mnemonic::POP_R(Register::SI),
0x5F => Mnemonic::POP_R(Register::DI),
0x60..=0x6F => panic!("0x06 to 0x06F is considered undefined."),
0x60..=0x6F => panic!("{:#x} is considered undefined", opcode),
0x70 => Mnemonic::JO(self.parse_byte()),
0x71 => Mnemonic::JNO(self.parse_byte()),
@@ -387,9 +387,10 @@ impl Disassembler {
0x7E => Mnemonic::JLE(self.parse_byte()),
0x7F => Mnemonic::JG(self.parse_byte()),
0x80 => modrmgprb!(self),
0x81 => modrmgprv!(self),
0x82 => modrmgprb!(self), // same as 0x80
// Group 1
0x80 => modrmgpr1b!(self),
0x81 => modrmgpr1v!(self),
0x82 => modrmgpr1b!(self), // same as 0x80
0x83 => panic!("Sign extented GPR1 not yet implemented"),
0x84 => modrmb!(self, TEST),
@@ -440,9 +441,55 @@ impl Disassembler {
0x9E => Mnemonic::SAHF,
0x9F => Mnemonic::LAHF,
0xA0 => Mnemonic::MOV_AL0b(self.parse_byte()),
0xA1 => Mnemonic::MOV_AX0v(self.parse_word()),
0xA2 => Mnemonic::MOV_0bAL(self.parse_byte()),
0xA3 => Mnemonic::MOV_0vAX(self.parse_word()),
0xA4 => Mnemonic::MOVSB,
0xA5 => Mnemonic::MOVSW,
0xA6 => Mnemonic::CMPSB,
0xA7 => Mnemonic::CMPSW,
0xA8 => Mnemonic::TEST_ALIb(self.parse_byte()),
0xA9 => Mnemonic::TEST_AXIv(self.parse_word()),
0xAA => Mnemonic::STOSB,
0xAB => Mnemonic::STOSW,
0xAC => Mnemonic::LODSB,
0xAD => Mnemonic::LODSW,
0xAE => Mnemonic::SCASB,
0xAF => Mnemonic::SCASW,
0xB0 => Mnemonic::MOV_ALIb(self.parse_byte()),
0xB1 => Mnemonic::MOV_CLIb(self.parse_byte()),
0xB2 => Mnemonic::MOV_DLIb(self.parse_byte()),
0xB3 => Mnemonic::MOV_BLIb(self.parse_byte()),
0xB4 => Mnemonic::MOV_AHIb(self.parse_byte()),
0xB5 => Mnemonic::MOV_CHIb(self.parse_byte()),
0xB6 => Mnemonic::MOV_DHIb(self.parse_byte()),
0xB7 => Mnemonic::MOV_BHIb(self.parse_byte()),
0xB8 => Mnemonic::MOV_AXIv(self.parse_word()),
0xB9 => Mnemonic::MOV_CXIv(self.parse_word()),
0xBA => Mnemonic::MOV_DXIv(self.parse_word()),
0xBB => Mnemonic::MOV_BXIv(self.parse_word()),
0xBC => Mnemonic::MOV_SPIv(self.parse_word()),
0xBD => Mnemonic::MOV_BPIv(self.parse_word()),
0xBE => Mnemonic::MOV_SIIv(self.parse_word()),
0xBF => Mnemonic::MOV_DIIv(self.parse_word()),
0xC0..=0xC1 => panic!("{:#x} is considered in undefined", opcode),
0xC2 => Mnemonic::RETIw(self.parse_word()),
0xC3 => Mnemonic::RET,
0xC4..=0xC5 => panic!("{:#x} not yet implemented (LDS or LES)", opcode),
0xC8..=0xC9 => panic!("{:#x} is considered in undefined", opcode),
0xCD => Mnemonic::INT(self.parse_byte()),
0xBB => Mnemonic::MOV_BXIv(self.parse_word()),
// Group 3
_ => {
eprintln!("Encountered unknown instruction '0x{:x}'", opcode);
eprintln!("Offset might be misaligned and data is being interpreted.");

View File

@@ -29,7 +29,7 @@ macro_rules! modrms {
/// Generate the resulting Mnemonic from a GPR instruction with Byte-sized
/// Immediate, encoded in a ModRM byte.
/// GPR always has an imm value as second operand.
macro_rules! modrmgprb {
macro_rules! modrmgpr1b {
($self:ident) => {{
let (target, reg) = $self.parse_modrm_byte(Operand::Byte(0));
let imm = $self.parse_byte();
@@ -41,7 +41,7 @@ macro_rules! modrmgprb {
/// Generate the resulting Mnemonic from a GPR instruction with Word-sized
/// Immediate, encoded in a ModRM byte.
/// GPR always has an imm value as second operand.
macro_rules! modrmgprv {
macro_rules! modrmgpr1v {
($self:ident) => {{
let (target, reg) = $self.parse_modrm_byte(Operand::Word(0));
let imm = $self.parse_word();

View File

@@ -160,6 +160,8 @@ pub enum Mnemonic {
JG(Byte),
// TEST
TEST(ModRmTarget, Register),
TEST_ALIb(Byte),
TEST_AXIv(Word),
//XHCG
XHCG(ModRmTarget, Register),
XCHG_AX(Register), // from AX
@@ -168,7 +170,27 @@ pub enum Mnemonic {
MOV_ToReg(ModRmTarget, Register),
MOV_FromSReg(ModRmTarget, SegmentRegister),
MOV_ToSReg(ModRmTarget, SegmentRegister),
MOV_AL0b(Byte),
MOV_AX0v(Word),
MOV_0bAL(Byte),
MOV_0vAX(Word),
MOV_ALIb(Byte),
MOV_CLIb(Byte),
MOV_DLIb(Byte),
MOV_BLIb(Byte),
MOV_AHIb(Byte),
MOV_CHIb(Byte),
MOV_DHIb(Byte),
MOV_BHIb(Byte),
MOV_AXIv(Word),
MOV_CXIv(Word),
MOV_DXIv(Word),
MOV_BXIv(Word),
MOV_SPIv(Word),
MOV_BPIv(Word),
MOV_SIIv(Word),
MOV_DIIv(Word),
// LEA
LEA(ModRmTarget, Register),
// Sign extensions
@@ -183,6 +205,23 @@ pub enum Mnemonic {
POPF,
SAHF,
LAHF,
// String Byte Operations
MOVSB,
MOVSW,
CMPSB,
CMPSW,
STOSB,
STOSW,
LODSB,
LODSW,
SCASB,
SCASW,
// RET
RETIw(Word),
RET,
// Load ES/DS Register
LES(ModRmTarget),
LDS(ModRmTarget),
// INT
INT(Byte),
}