aboutsummaryrefslogtreecommitdiff
path: root/src/protected_mode
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-08-15 11:38:15 -0700
committeriximeow <me@iximeow.net>2020-08-15 11:39:04 -0700
commita0b1fddbb55cbab9d482d4f8cffc7ffe87f73864 (patch)
tree0f94f4bb1809dbdf3ef01170884757d0488f78c1 /src/protected_mode
parent6248d3c5f7dd196acdfce5c0da1608fed81b43cd (diff)
add register class constants to allow reasoning about register operands0.1.1
also bump to 0.1.1
Diffstat (limited to 'src/protected_mode')
-rw-r--r--src/protected_mode/mod.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 315cb58..b9d626c 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -506,6 +506,87 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[
"eflags",
];
+/// high-level register classes in an x86 machine, such as "8-byte general purpose", "xmm", "x87",
+/// and so on. constants in this module are useful for inspecting the register class of a decoded
+/// instruction. as an example:
+/// ```
+/// extern crate yaxpeax_arch;
+/// use yaxpeax_x86::protected_mode::{self as amd64};
+/// use yaxpeax_x86::protected_mode::{Opcode, Operand, RegisterClass};
+/// use yaxpeax_arch::Decoder;
+///
+/// let movsx_eax_cl = &[0x0f, 0xbe, 0xc1];
+/// let decoder = amd64::InstDecoder::default();
+/// let instruction = decoder
+/// .decode(movsx_eax_cl.into_iter().cloned())
+/// .expect("can decode");
+///
+/// assert_eq!(instruction.opcode(), Opcode::MOVSX_b);
+///
+/// fn show_register_class_info(regclass: RegisterClass) {
+/// match regclass {
+/// amd64::register_class::D => {
+/// println!(" and is a dword register");
+/// }
+/// amd64::register_class::B => {
+/// println!(" and is a byte register");
+/// }
+/// other => {
+/// panic!("unexpected and invalid register class {:?}", other);
+/// }
+/// }
+/// }
+///
+/// if let Operand::Register(regspec) = instruction.operand(0) {
+/// println!("first operand is {}", regspec);
+/// show_register_class_info(regspec.class());
+/// }
+///
+/// if let Operand::Register(regspec) = instruction.operand(1) {
+/// println!("first operand is {}", regspec);
+/// show_register_class_info(regspec.class());
+/// }
+/// ```
+///
+/// this is preferable to alternatives like checking register names against a known list: a
+/// register class is one byte and "is qword general-purpose" can then be a simple one-byte
+/// compare, instead of 16 string compares.
+///
+/// `yaxpeax-x86` does not attempt to further distinguish between, for example, register
+/// suitability as operands. as an example, `cl` is only a byte register, with no additional
+/// register class to describe its use as an implicit shift operand.
+pub mod register_class {
+ use super::{RegisterBank, RegisterClass};
+ /// doubleword registers: eax through edi.
+ pub const D: RegisterClass = RegisterClass { kind: RegisterBank::D };
+ /// word registers: ax through di.
+ pub const W: RegisterClass = RegisterClass { kind: RegisterBank::W };
+ /// byte registers: al, cl, dl, bl, ah, ch, dh, bh.
+ pub const B: RegisterClass = RegisterClass { kind: RegisterBank::B };
+ /// control registers cr0 through cr7.
+ pub const CR: RegisterClass = RegisterClass { kind: RegisterBank::CR};
+ /// debug registers dr0 through dr7.
+ pub const DR: RegisterClass = RegisterClass { kind: RegisterBank::DR };
+ /// segment registers es, cs, ss, ds, fs, gs.
+ pub const S: RegisterClass = RegisterClass { kind: RegisterBank::S };
+ /// xmm registers xmm0 through xmm31.
+ pub const X: RegisterClass = RegisterClass { kind: RegisterBank::X };
+ /// ymm registers ymm0 through ymm31.
+ pub const Y: RegisterClass = RegisterClass { kind: RegisterBank::Y };
+ /// zmm registers zmm0 through zmm31.
+ pub const Z: RegisterClass = RegisterClass { kind: RegisterBank::Z };
+ /// x87 floating point stack entries st(0) through st(7).
+ pub const ST: RegisterClass = RegisterClass { kind: RegisterBank::ST };
+ /// mmx registers mm0 through mm7.
+ pub const MM: RegisterClass = RegisterClass { kind: RegisterBank::MM };
+ /// `AVX512` mask registers k0 through k7.
+ pub const K: RegisterClass = RegisterClass { kind: RegisterBank::K };
+ /// the full instruction pointer register.
+ pub const EIP: RegisterClass = RegisterClass { kind: RegisterBank::EIP };
+ /// the full cpu flags register.
+ pub const EFLAGS: RegisterClass = RegisterClass { kind: RegisterBank::EFlags };
+}
+
impl RegisterClass {
/// return a human-friendly name for this register class
pub fn name(&self) -> &'static str {