From 876fc7449cf862e7ffe788885fb7d4209ad2eb5d Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 3 May 2020 13:54:02 -0700 Subject: add width() to ask width of an x86 operand this is largely wrong for memory operands, which require more invasive changes --- src/long_mode/mod.rs | 106 +++++++++++++++++++++++++++++++++++++++++ src/protected_mode/mod.rs | 85 +++++++++++++++++++++++++++++++-- test/long_mode/mod.rs | 1 + test/long_mode/operand.rs | 17 +++++++ test/protected_mode/mod.rs | 1 + test/protected_mode/operand.rs | 16 +++++++ 6 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 test/long_mode/operand.rs create mode 100644 test/protected_mode/operand.rs diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 3319141..05eee0a 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -179,6 +179,21 @@ impl RegSpec { } #[inline] + pub fn ecx() -> RegSpec { + RegSpec { bank: RegisterBank::D, num: 1 } + } + + #[inline] + pub fn edx() -> RegSpec { + RegSpec { bank: RegisterBank::D, num: 2 } + } + + #[inline] + pub fn ebx() -> RegSpec { + RegSpec { bank: RegisterBank::D, num: 3 } + } + + #[inline] pub fn ax() -> RegSpec { RegSpec { bank: RegisterBank::W, num: 0 } } @@ -197,6 +212,66 @@ impl RegSpec { pub fn cl() -> RegSpec { RegSpec { bank: RegisterBank::B, num: 1 } } + + #[inline] + pub fn ah() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 4 } + } + + #[inline] + pub fn ch() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 5 } + } + + #[inline] + pub fn width(&self) -> u8 { + match self.bank { + RegisterBank::Q => 8, + RegisterBank::D => 4, + RegisterBank::W => 2, + RegisterBank::B | + RegisterBank::rB => { + 1 + }, + RegisterBank::CR | + RegisterBank::DR => { + 8 + }, + RegisterBank::S => { + 2 + }, + RegisterBank::EIP => { + 4 + } + RegisterBank::RIP => { + 8 + } + RegisterBank::EFlags => { + 4 + } + RegisterBank::RFlags => { + 8 + } + RegisterBank::X => { + 16 + } + RegisterBank::Y => { + 32 + } + RegisterBank::Z => { + 64 + } + RegisterBank::ST => { + 10 + } + RegisterBank::MM => { + 8 + } + RegisterBank::K => { + 8 + } + } + } } #[allow(non_camel_case_types)] @@ -361,6 +436,37 @@ impl Operand { } } } + + pub fn width(&self) -> u8 { + match self { + Operand::Nothing => { + panic!("non-operand does not have a size"); + } + Operand::Register(reg) => { + reg.width() + } + Operand::ImmediateI8(_) | + Operand::ImmediateU8(_) => { + 1 + } + Operand::ImmediateI16(_) | + Operand::ImmediateU16(_) => { + 2 + } + Operand::ImmediateI32(_) | + Operand::ImmediateU32(_) => { + 4 + } + Operand::ImmediateI64(_) | + Operand::ImmediateU64(_) => { + 8 + } + // memory operands + _ => { + 8 + } + } + } } #[test] diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 2a32a91..76af3a1 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -145,13 +145,13 @@ impl RegSpec { } #[inline] - pub fn bx() -> RegSpec { - RegSpec { bank: RegisterBank::W, num: 3 } + pub fn ebx() -> RegSpec { + RegSpec { bank: RegisterBank::D, num: 3 } } #[inline] - pub fn ebx() -> RegSpec { - RegSpec { bank: RegisterBank::D, num: 3 } + pub fn bx() -> RegSpec { + RegSpec { bank: RegisterBank::W, num: 3 } } #[inline] @@ -193,6 +193,56 @@ impl RegSpec { pub fn cl() -> RegSpec { RegSpec { bank: RegisterBank::B, num: 1 } } + + #[inline] + pub fn ah() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 4 } + } + + #[inline] + pub fn ch() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 5 } + } + + #[inline] + pub fn width(&self) -> u8 { + match self.bank { + RegisterBank::D => 4, + RegisterBank::W => 2, + RegisterBank::B => 1, + RegisterBank::CR | + RegisterBank::DR => { + 4 + }, + RegisterBank::S => { + 2 + }, + RegisterBank::EIP => { + 4 + } + RegisterBank::EFlags => { + 4 + } + RegisterBank::X => { + 16 + } + RegisterBank::Y => { + 32 + } + RegisterBank::Z => { + 64 + } + RegisterBank::ST => { + 10 + } + RegisterBank::MM => { + 8 + } + RegisterBank::K => { + 8 + } + } + } } #[allow(non_camel_case_types)] @@ -347,6 +397,33 @@ impl Operand { } } } + + pub fn width(&self) -> u8 { + match self { + Operand::Nothing => { + panic!("non-operand does not have a size"); + } + Operand::Register(reg) => { + reg.width() + } + Operand::ImmediateI8(_) | + Operand::ImmediateU8(_) => { + 1 + } + Operand::ImmediateI16(_) | + Operand::ImmediateU16(_) => { + 2 + } + Operand::ImmediateI32(_) | + Operand::ImmediateU32(_) => { + 4 + } + // memory operands + _ => { + 4 + } + } + } } #[test] diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index addaae4..2fbe4fb 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1,4 +1,5 @@ mod regspec; +mod operand; use std::fmt::Write; diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs new file mode 100644 index 0000000..885c6d1 --- /dev/null +++ b/test/long_mode/operand.rs @@ -0,0 +1,17 @@ +use yaxpeax_arch::{Decoder, LengthedInstruction}; +use yaxpeax_x86::long_mode::{DecodeError, InstDecoder, Opcode}; + +#[test] +fn register_widths() { + assert_eq!(Operand::Register(RegSpec::rsp()).width(), 8); + assert_eq!(Operand::Register(RegSpec::esp()).width(), 4); + assert_eq!(Operand::Register(RegSpec::sp()).width(), 2); + assert_eq!(Operand::Register(RegSpec::cl()).width(), 1); + assert_eq!(Operand::Register(RegSpec::ch()).width(), 1); + assert_eq!(Operand::Register(RegSpec::gs()).width(), 2); +} + +#[test] +fn memory_widths() { + assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 8); +} diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 37a3b24..ab3cdc8 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -1,4 +1,5 @@ mod regspec; +mod operand; use std::fmt::Write; diff --git a/test/protected_mode/operand.rs b/test/protected_mode/operand.rs new file mode 100644 index 0000000..08a24be --- /dev/null +++ b/test/protected_mode/operand.rs @@ -0,0 +1,16 @@ +use yaxpeax_arch::{Decoder, LengthedInstruction}; +use yaxpeax_x86::long_mode::{DecodeError, InstDecoder, Opcode}; + +#[test] +fn register_widths() { + assert_eq!(Operand::Register(RegSpec::esp()).width(), 4); + assert_eq!(Operand::Register(RegSpec::sp()).width(), 2); + assert_eq!(Operand::Register(RegSpec::cl()).width(), 1); + assert_eq!(Operand::Register(RegSpec::ch()).width(), 1); + assert_eq!(Operand::Register(RegSpec::gs()).width(), 2); +} + +#[test] +fn memory_widths() { + assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 4); +} -- cgit v1.1