dynasmrt/
x86.rs

1//! Runtime support for the x86 architecture assembling target.
2//!
3//! The x86 instruction set features variable-length instructions and
4//! relative relocations up to 16 bits in size, or absolute relocations of 32 bits in size.
5//!
6//! The core relocation behaviour for this architecture is provided by the [`X86Relocation`] type.
7//!
8//! Next to that, this module contains the following:
9//!
10//! ## Type aliases
11//!
12//! Several specialized type aliases of the generic [`Assembler`] are provided as these are by far the most common usecase.
13//!
14//! ## Enums
15//!
16//! There are enumerator of every logically distinct register family usable in x86. 
17//! These enums implement the [`Register`] trait and their discriminant values match their numeric encoding in dynamic register literals.
18//!
19//! *Note: The presence of some registers listed here is purely what is encodable. Check the relevant architecture documentation to find what is architecturally valid.*
20
21
22use crate::Register;
23use crate::relocations::{Relocation, RelocationSize, RelocationKind, ImpossibleRelocation};
24
25
26/// Relocation implementation for the x86 architecture.
27#[derive(Debug, Clone)]
28pub struct X86Relocation {
29    size: RelocationSize,
30    kind: RelocationKind,
31}
32
33impl Relocation for X86Relocation {
34    type Encoding = (u8, u8);
35    fn from_encoding(encoding: Self::Encoding) -> Self {
36        Self {
37            size: RelocationSize::from_encoding(encoding.0),
38            kind: RelocationKind::from_encoding(encoding.1),
39        }
40    }
41    fn from_size(size: RelocationSize) -> Self {
42        Self {
43            size,
44            kind: RelocationKind::Relative,
45        }
46    }
47    fn size(&self) -> usize {
48        self.size.size()
49    }
50    fn write_value(&self, buf: &mut [u8], value: isize) -> Result<(), ImpossibleRelocation> {
51        self.size.write_value(buf, value)
52    }
53    fn read_value(&self, buf: &[u8]) -> isize {
54        self.size.read_value(buf)
55    }
56    fn kind(&self) -> RelocationKind {
57        self.kind
58    }
59    fn page_size() -> usize {
60        4096
61    }
62}
63
64
65/// An x86 Assembler. This is aliased here for backwards compatability.
66pub type Assembler = crate::Assembler<X86Relocation>;
67/// An x86 AssemblyModifier. This is aliased here for backwards compatability.
68pub type AssemblyModifier<'a> = crate::Modifier<'a, X86Relocation>;
69/// An x86 UncommittedModifier. This is aliased here for backwards compatability.
70pub type UncommittedModifier<'a> = crate::UncommittedModifier<'a>;
71
72
73/// 1, 2 or 4-byte general purpose "double-word" registers.
74///
75/// EIP does not appear here as it cannot be addressed dynamically.
76#[allow(missing_docs)]
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
78pub enum Rd {
79    EAX = 0x00, ECX = 0x01, EDX = 0x02, EBX = 0x03,
80    ESP = 0x04, EBP = 0x05, ESI = 0x06, EDI = 0x07,
81}
82reg_impls!(Rd);
83
84/// High-byte general purpose registers.
85#[allow(missing_docs)]
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub enum Rh {
88    AH = 0x4, CH = 0x5, DH = 0x6, BH = 0x7,
89}
90reg_impls!(Rh);
91
92/// 10-byte floating point registers.
93#[allow(missing_docs)]
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
95pub enum Rf {
96    ST0 = 0x0, ST1 = 0x1, ST2 = 0x2, ST3 = 0x3,
97    ST4 = 0x4, ST5 = 0x5, ST6 = 0x6, ST7 = 0x7,
98}
99reg_impls!(Rf);
100
101/// 8-byte MMX registers.
102#[allow(missing_docs)]
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
104pub enum Rm {
105    MMX0 = 0x0, MMX1 = 0x1, MMX2 = 0x2, MMX3 = 0x3,
106    MMX4 = 0x4, MMX5 = 0x5, MMX6 = 0x6, MMX7 = 0x7,
107}
108reg_impls!(Rm);
109
110/// 16 or 32-byte SSE registers.
111#[allow(missing_docs)]
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
113pub enum Rx {
114    XMM0  = 0x0, XMM1  = 0x1, XMM2  = 0x2, XMM3  = 0x3,
115    XMM4  = 0x4, XMM5  = 0x5, XMM6  = 0x6, XMM7  = 0x7,
116}
117reg_impls!(Rx);
118
119/// 2-byte segment registers.
120#[allow(missing_docs)]
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122pub enum Rs {
123    ES = 0x0, CS = 0x1, SS = 0x2, DS = 0x3,
124    FS = 0x4, GS = 0x5,
125}
126reg_impls!(Rs);
127
128/// 4-byte control registers.
129#[allow(missing_docs)]
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
131pub enum RC {
132    CR0  = 0x0, CR1  = 0x1, CR2  = 0x2, CR3  = 0x3,
133    CR4  = 0x4, CR5  = 0x5, CR6  = 0x6, CR7  = 0x7,
134}
135reg_impls!(RC);
136
137/// 4-byte debug registers.
138#[allow(missing_docs)]
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
140pub enum RD {
141    DR0  = 0x0, DR1  = 0x1, DR2  = 0x2, DR3  = 0x3,
142    DR4  = 0x4, DR5  = 0x5, DR6  = 0x6, DR7  = 0x7,
143    DR8  = 0x8, DR9  = 0x9, DR10 = 0xA, DR11 = 0xB,
144    DR12 = 0xC, DR13 = 0xD, DR14 = 0xE, DR15 = 0xF,
145}
146reg_impls!(RD);
147
148/// 16-byte bound registers.
149#[allow(missing_docs)]
150#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
151pub enum RB {
152    BND0 = 0x0, BND1 = 0x1, BND2 = 0x2, BND3 = 0x3
153}
154reg_impls!(RB);
155
156#[cfg(test)]
157mod tests {
158    use super::Rd::*;
159    use crate::Register;
160
161    #[test]
162    fn reg_code() {
163        assert_eq!(EAX.code(), 0);
164    }
165
166    #[test]
167    fn reg_code_from() {
168        assert_eq!(u8::from(ECX), 1);
169    }
170}