Expand description
Decodes 16/32/64-bit x86 instructions
Implementations§
source§impl<'a> Decoder<'a>
impl<'a> Decoder<'a>
sourcepub fn new(bitness: u32, data: &'a [u8], options: u32) -> Decoder<'a>
pub fn new(bitness: u32, data: &'a [u8], options: u32) -> Decoder<'a>
Creates a decoder
Panics
Panics if bitness
is not one of 16, 32, 64.
Arguments
bitness
: 16, 32 or 64data
: Data to decodeoptions
: Decoder options,0
or eg.DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD
Examples
use iced_x86::*;
// xchg ah,[rdx+rsi+16h]
// xacquire lock add dword ptr [rax],5Ah
// vmovdqu64 zmm18{k3}{z},zmm11
let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3";
let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
decoder.set_ip(0x1234_5678);
let instr1 = decoder.decode();
assert_eq!(instr1.code(), Code::Xchg_rm8_r8);
assert_eq!(instr1.mnemonic(), Mnemonic::Xchg);
assert_eq!(instr1.len(), 4);
let instr2 = decoder.decode();
assert_eq!(instr2.code(), Code::Add_rm32_imm8);
assert_eq!(instr2.mnemonic(), Mnemonic::Add);
assert_eq!(instr2.len(), 5);
let instr3 = decoder.decode();
assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512);
assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64);
assert_eq!(instr3.len(), 6);
It’s sometimes useful to decode some invalid instructions, eg. lock add esi,ecx
.
Pass in DecoderOptions::NO_INVALID_CHECK
to the constructor and the decoder
will decode some invalid encodings.
use iced_x86::*;
// lock add esi,ecx ; lock not allowed
let bytes = b"\xF0\x01\xCE";
let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
decoder.set_ip(0x1234_5678);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::INVALID);
// We want to decode some instructions with invalid encodings
let mut decoder = Decoder::new(64, bytes, DecoderOptions::NO_INVALID_CHECK);
decoder.set_ip(0x1234_5678);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert!(instr.has_lock_prefix());
sourcepub fn with_ip(bitness: u32, data: &'a [u8], ip: u64, options: u32) -> Decoder<'a>
pub fn with_ip(bitness: u32, data: &'a [u8], ip: u64, options: u32) -> Decoder<'a>
Creates a decoder
Panics
Panics if bitness
is not one of 16, 32, 64.
Arguments
bitness
: 16, 32 or 64data
: Data to decodeip
:RIP
valueoptions
: Decoder options,0
or eg.DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD
Examples
use iced_x86::*;
// xchg ah,[rdx+rsi+16h]
// xacquire lock add dword ptr [rax],5Ah
// vmovdqu64 zmm18{k3}{z},zmm11
let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
let instr1 = decoder.decode();
assert_eq!(instr1.code(), Code::Xchg_rm8_r8);
assert_eq!(instr1.mnemonic(), Mnemonic::Xchg);
assert_eq!(instr1.len(), 4);
let instr2 = decoder.decode();
assert_eq!(instr2.code(), Code::Add_rm32_imm8);
assert_eq!(instr2.mnemonic(), Mnemonic::Add);
assert_eq!(instr2.len(), 5);
let instr3 = decoder.decode();
assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512);
assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64);
assert_eq!(instr3.len(), 6);
It’s sometimes useful to decode some invalid instructions, eg. lock add esi,ecx
.
Pass in DecoderOptions::NO_INVALID_CHECK
to the constructor and the decoder
will decode some invalid encodings.
use iced_x86::*;
// lock add esi,ecx ; lock not allowed
let bytes = b"\xF0\x01\xCE";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::INVALID);
// We want to decode some instructions with invalid encodings
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NO_INVALID_CHECK);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert!(instr.has_lock_prefix());
sourcepub fn try_new(
bitness: u32,
data: &'a [u8],
options: u32
) -> Result<Decoder<'a>, IcedError>
pub fn try_new(
bitness: u32,
data: &'a [u8],
options: u32
) -> Result<Decoder<'a>, IcedError>
Creates a decoder
Errors
Fails if bitness
is not one of 16, 32, 64.
Arguments
bitness
: 16, 32 or 64data
: Data to decodeoptions
: Decoder options,0
or eg.DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD
Examples
use iced_x86::*;
// xchg ah,[rdx+rsi+16h]
// xacquire lock add dword ptr [rax],5Ah
// vmovdqu64 zmm18{k3}{z},zmm11
let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3";
let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap();
decoder.set_ip(0x1234_5678);
let instr1 = decoder.decode();
assert_eq!(instr1.code(), Code::Xchg_rm8_r8);
assert_eq!(instr1.mnemonic(), Mnemonic::Xchg);
assert_eq!(instr1.len(), 4);
let instr2 = decoder.decode();
assert_eq!(instr2.code(), Code::Add_rm32_imm8);
assert_eq!(instr2.mnemonic(), Mnemonic::Add);
assert_eq!(instr2.len(), 5);
let instr3 = decoder.decode();
assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512);
assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64);
assert_eq!(instr3.len(), 6);
It’s sometimes useful to decode some invalid instructions, eg. lock add esi,ecx
.
Pass in DecoderOptions::NO_INVALID_CHECK
to the constructor and the decoder
will decode some invalid encodings.
use iced_x86::*;
// lock add esi,ecx ; lock not allowed
let bytes = b"\xF0\x01\xCE";
let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap();
decoder.set_ip(0x1234_5678);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::INVALID);
// We want to decode some instructions with invalid encodings
let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NO_INVALID_CHECK).unwrap();
decoder.set_ip(0x1234_5678);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert!(instr.has_lock_prefix());
sourcepub fn try_with_ip(
bitness: u32,
data: &'a [u8],
ip: u64,
options: u32
) -> Result<Decoder<'a>, IcedError>
pub fn try_with_ip(
bitness: u32,
data: &'a [u8],
ip: u64,
options: u32
) -> Result<Decoder<'a>, IcedError>
Creates a decoder
Errors
Fails if bitness
is not one of 16, 32, 64.
Arguments
bitness
: 16, 32 or 64data
: Data to decodeip
:RIP
valueoptions
: Decoder options,0
or eg.DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD
Examples
use iced_x86::*;
// xchg ah,[rdx+rsi+16h]
// xacquire lock add dword ptr [rax],5Ah
// vmovdqu64 zmm18{k3}{z},zmm11
let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3";
let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE).unwrap();
let instr1 = decoder.decode();
assert_eq!(instr1.code(), Code::Xchg_rm8_r8);
assert_eq!(instr1.mnemonic(), Mnemonic::Xchg);
assert_eq!(instr1.len(), 4);
let instr2 = decoder.decode();
assert_eq!(instr2.code(), Code::Add_rm32_imm8);
assert_eq!(instr2.mnemonic(), Mnemonic::Add);
assert_eq!(instr2.len(), 5);
let instr3 = decoder.decode();
assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512);
assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64);
assert_eq!(instr3.len(), 6);
It’s sometimes useful to decode some invalid instructions, eg. lock add esi,ecx
.
Pass in DecoderOptions::NO_INVALID_CHECK
to the constructor and the decoder
will decode some invalid encodings.
use iced_x86::*;
// lock add esi,ecx ; lock not allowed
let bytes = b"\xF0\x01\xCE";
let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE).unwrap();
let instr = decoder.decode();
assert_eq!(instr.code(), Code::INVALID);
// We want to decode some instructions with invalid encodings
let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NO_INVALID_CHECK).unwrap();
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert!(instr.has_lock_prefix());
Examples found in repository?
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
pub fn with_ip(bitness: u32, data: &'a [u8], ip: u64, options: u32) -> Decoder<'a> {
Decoder::try_with_ip(bitness, data, ip, options).unwrap()
}
/// Creates a decoder
///
/// # Errors
///
/// Fails if `bitness` is not one of 16, 32, 64.
///
/// # Arguments
///
/// * `bitness`: 16, 32 or 64
/// * `data`: Data to decode
/// * `options`: Decoder options, `0` or eg. `DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD`
///
/// # Examples
///
/// ```
/// use iced_x86::*;
///
/// // xchg ah,[rdx+rsi+16h]
/// // xacquire lock add dword ptr [rax],5Ah
/// // vmovdqu64 zmm18{k3}{z},zmm11
/// let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3";
/// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap();
/// decoder.set_ip(0x1234_5678);
///
/// let instr1 = decoder.decode();
/// assert_eq!(instr1.code(), Code::Xchg_rm8_r8);
/// assert_eq!(instr1.mnemonic(), Mnemonic::Xchg);
/// assert_eq!(instr1.len(), 4);
///
/// let instr2 = decoder.decode();
/// assert_eq!(instr2.code(), Code::Add_rm32_imm8);
/// assert_eq!(instr2.mnemonic(), Mnemonic::Add);
/// assert_eq!(instr2.len(), 5);
///
/// let instr3 = decoder.decode();
/// assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512);
/// assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64);
/// assert_eq!(instr3.len(), 6);
/// ```
///
/// It's sometimes useful to decode some invalid instructions, eg. `lock add esi,ecx`.
/// Pass in [`DecoderOptions::NO_INVALID_CHECK`] to the constructor and the decoder
/// will decode some invalid encodings.
///
/// [`DecoderOptions::NO_INVALID_CHECK`]: struct.DecoderOptions.html#associatedconstant.NO_INVALID_CHECK
///
/// ```
/// use iced_x86::*;
///
/// // lock add esi,ecx ; lock not allowed
/// let bytes = b"\xF0\x01\xCE";
/// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap();
/// decoder.set_ip(0x1234_5678);
/// let instr = decoder.decode();
/// assert_eq!(instr.code(), Code::INVALID);
///
/// // We want to decode some instructions with invalid encodings
/// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NO_INVALID_CHECK).unwrap();
/// decoder.set_ip(0x1234_5678);
/// let instr = decoder.decode();
/// assert_eq!(instr.code(), Code::Add_rm32_r32);
/// assert!(instr.has_lock_prefix());
/// ```
#[inline]
pub fn try_new(bitness: u32, data: &'a [u8], options: u32) -> Result<Decoder<'a>, IcedError> {
Decoder::try_with_ip(bitness, data, 0, options)
}
sourcepub const fn ip(&self) -> u64
pub const fn ip(&self) -> u64
Gets the current IP
/EIP
/RIP
value, see also position()
sourcepub fn set_ip(&mut self, new_value: u64)
pub fn set_ip(&mut self, new_value: u64)
Sets the current IP
/EIP
/RIP
value, see also try_set_position()
This method only updates the IP value, it does not change the data position, use try_set_position()
to change the position.
Arguments
new_value
: New IP
sourcepub const fn bitness(&self) -> u32
pub const fn bitness(&self) -> u32
Gets the bitness (16, 32 or 64)
Examples found in repository?
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
fn decode(_self_ptr: *const OpCodeHandler, decoder: &mut Decoder<'_>, instruction: &mut Instruction) {
debug_assert_eq!(decoder.state.encoding(), EncodingKind::Legacy as u32);
const _: () = assert!(OpKind::Register as u32 == 0);
//instruction.set_op0_kind(OpKind::Register);
instruction.set_op0_register(unsafe { mem::transmute((decoder.state.reg + Register::MM0 as u32) as RegisterUnderlyingType) });
if decoder.state.mod_ == 3 {
const _: () = assert!(OpKind::Register as u32 == 0);
//instruction.set_op1_kind(OpKind::Register);
instruction.set_op1_register(unsafe { mem::transmute((decoder.state.rm + Register::MM0 as u32) as RegisterUnderlyingType) });
} else {
read_op_mem_stmt!(decoder, instruction, {
instruction.set_op1_kind(OpKind::Memory);
});
}
let ib = decoder.read_u8();
let mut code = CODE_VALUES[ib];
match code {
Code::D3NOW_Pfrcpv_mm_mmm64 | Code::D3NOW_Pfrsqrtv_mm_mmm64 => {
if (decoder.options & DecoderOptions::CYRIX) == 0 || decoder.bitness() == 64 {
code = Code::INVALID;
}
}
_ => {}
}
instruction.set_code(code);
if code == Code::INVALID {
decoder.set_invalid_instruction();
}
}
sourcepub const fn max_position(&self) -> usize
pub const fn max_position(&self) -> usize
Gets the max value that can be passed to try_set_position()
. This is the size of the data that gets
decoded to instructions and it’s the length of the slice that was passed to the constructor.
sourcepub fn position(&self) -> usize
pub fn position(&self) -> usize
Gets the current data position. This value is always <= max_position()
.
When position()
== max_position()
, it’s not possible to decode more
instructions and can_decode()
returns false
.
sourcepub fn set_position(&mut self, new_pos: usize) -> Result<(), IcedError>
pub fn set_position(&mut self, new_pos: usize) -> Result<(), IcedError>
Sets the current data position, which is the index into the data passed to the constructor.
This value is always <= max_position()
Errors
Fails if the new position is invalid.
Arguments
new_pos
: New position and must be <=max_position()
Examples
use iced_x86::*;
// nop and pause
let bytes = b"\x90\xF3\x90";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
assert_eq!(decoder.position(), 0);
assert_eq!(decoder.max_position(), 3);
let instr = decoder.decode();
assert_eq!(decoder.position(), 1);
assert_eq!(instr.code(), Code::Nopd);
let instr = decoder.decode();
assert_eq!(decoder.position(), 3);
assert_eq!(instr.code(), Code::Pause);
// Start all over again
decoder.set_position(0).unwrap();
decoder.set_ip(0x1234_5678);
assert_eq!(decoder.position(), 0);
assert_eq!(decoder.decode().code(), Code::Nopd);
assert_eq!(decoder.decode().code(), Code::Pause);
assert_eq!(decoder.position(), 3);
sourcepub fn can_decode(&self) -> bool
pub fn can_decode(&self) -> bool
Returns true
if there’s at least one more byte to decode. It doesn’t verify that the
next instruction is valid, it only checks if there’s at least one more byte to read.
See also position()
and max_position()
It’s not required to call this method. If this method returns false
, then decode_out()
and decode()
will return an instruction whose code()
== Code::INVALID
.
Examples
use iced_x86::*;
// nop and an incomplete instruction
let bytes = b"\x90\xF3\x0F";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
// 3 bytes left to read
assert!(decoder.can_decode());
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Nopd);
// 2 bytes left to read
assert!(decoder.can_decode());
let instr = decoder.decode();
// Not enough bytes left to decode a full instruction
assert_eq!(instr.code(), Code::INVALID);
// 0 bytes left to read
assert!(!decoder.can_decode());
Examples found in repository?
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
fn next(&mut self) -> Option<Self::Item> {
if self.decoder.can_decode() {
Some(self.decoder.decode())
} else {
None
}
}
}
impl FusedIterator for DecoderIter<'_, '_> {}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct DecoderIntoIter<'a> {
decoder: Decoder<'a>,
}
impl Iterator for DecoderIntoIter<'_> {
type Item = Instruction;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.decoder.can_decode() {
Some(self.decoder.decode())
} else {
None
}
}
sourcepub fn iter<'b>(&'b mut self) -> DecoderIter<'a, 'b>
pub fn iter<'b>(&'b mut self) -> DecoderIter<'a, 'b>
Returns an iterator that borrows this instance to decode instructions until there’s
no more data to decode, i.e., until can_decode()
returns false
.
Examples
use iced_x86::*;
// nop and pause
let bytes = b"\x90\xF3\x90";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
let mut iter = decoder.iter();
assert_eq!(iter.next().unwrap().code(), Code::Nopd);
assert_eq!(iter.next().unwrap().code(), Code::Pause);
assert!(iter.next().is_none());
for
loop:
use iced_x86::*;
let bytes = b"\x90\xF3\x90";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
for instr in &mut decoder { // or decoder.iter()
println!("code: {:?}", instr.code());
}
sourcepub const fn last_error(&self) -> DecoderError
pub const fn last_error(&self) -> DecoderError
Gets the last decoder error. Unless you need to know the reason it failed,
it’s better to check instruction.is_invalid()
.
sourcepub fn decode(&mut self) -> Instruction
pub fn decode(&mut self) -> Instruction
Decodes and returns the next instruction, see also decode_out(&mut Instruction)
which avoids copying the decoded instruction to the caller’s return variable.
See also last_error()
.
Examples
use iced_x86::*;
// xrelease lock add [rax],ebx
let bytes = b"\xF0\xF3\x01\x18";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
let instr = decoder.decode();
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert_eq!(instr.mnemonic(), Mnemonic::Add);
assert_eq!(instr.len(), 4);
assert_eq!(instr.op_count(), 2);
assert_eq!(instr.op0_kind(), OpKind::Memory);
assert_eq!(instr.memory_base(), Register::RAX);
assert_eq!(instr.memory_index(), Register::None);
assert_eq!(instr.memory_index_scale(), 1);
assert_eq!(instr.memory_displacement64(), 0);
assert_eq!(instr.memory_segment(), Register::DS);
assert_eq!(instr.segment_prefix(), Register::None);
assert_eq!(instr.memory_size(), MemorySize::UInt32);
assert_eq!(instr.op1_kind(), OpKind::Register);
assert_eq!(instr.op1_register(), Register::EBX);
assert!(instr.has_lock_prefix());
assert!(instr.has_xrelease_prefix());
Examples found in repository?
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
fn next(&mut self) -> Option<Self::Item> {
if self.decoder.can_decode() {
Some(self.decoder.decode())
} else {
None
}
}
}
impl FusedIterator for DecoderIter<'_, '_> {}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct DecoderIntoIter<'a> {
decoder: Decoder<'a>,
}
impl Iterator for DecoderIntoIter<'_> {
type Item = Instruction;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.decoder.can_decode() {
Some(self.decoder.decode())
} else {
None
}
}
sourcepub fn decode_out(&mut self, instruction: &mut Instruction)
pub fn decode_out(&mut self, instruction: &mut Instruction)
Decodes the next instruction. The difference between this method and decode()
is that this
method doesn’t need to copy the result to the caller’s return variable (saves 40 bytes of copying).
See also last_error()
.
Arguments
instruction
: Updated with the decoded instruction. All fields are initialized (it’s anout
argument)
Examples
use iced_x86::*;
// xrelease lock add [rax],ebx
let bytes = b"\xF0\xF3\x01\x18";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
let mut instr = Instruction::default();
decoder.decode_out(&mut instr);
assert_eq!(instr.code(), Code::Add_rm32_r32);
assert_eq!(instr.mnemonic(), Mnemonic::Add);
assert_eq!(instr.len(), 4);
assert_eq!(instr.op_count(), 2);
assert_eq!(instr.op0_kind(), OpKind::Memory);
assert_eq!(instr.memory_base(), Register::RAX);
assert_eq!(instr.memory_index(), Register::None);
assert_eq!(instr.memory_index_scale(), 1);
assert_eq!(instr.memory_displacement64(), 0);
assert_eq!(instr.memory_segment(), Register::DS);
assert_eq!(instr.segment_prefix(), Register::None);
assert_eq!(instr.memory_size(), MemorySize::UInt32);
assert_eq!(instr.op1_kind(), OpKind::Register);
assert_eq!(instr.op1_register(), Register::EBX);
assert!(instr.has_lock_prefix());
assert!(instr.has_xrelease_prefix());
sourcepub fn get_constant_offsets(&self, instruction: &Instruction) -> ConstantOffsets
pub fn get_constant_offsets(&self, instruction: &Instruction) -> ConstantOffsets
Gets the offsets of the constants (memory displacement and immediate) in the decoded instruction. The caller can check if there are any relocations at those addresses.
Arguments
instruction
: The latest instruction that was decoded by this decoder
Examples
use iced_x86::*;
// nop
// xor dword ptr [rax-5AA5EDCCh],5Ah
// 00 01 02 03 04 05 06
// \opc\mrm\displacement___\imm
let bytes = b"\x90\x83\xB3\x34\x12\x5A\xA5\x5A";
let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE);
assert_eq!(decoder.decode().code(), Code::Nopd);
let instr = decoder.decode();
let co = decoder.get_constant_offsets(&instr);
assert!(co.has_displacement());
assert_eq!(co.displacement_offset(), 2);
assert_eq!(co.displacement_size(), 4);
assert!(co.has_immediate());
assert_eq!(co.immediate_offset(), 6);
assert_eq!(co.immediate_size(), 1);
// It's not an instruction with two immediates (e.g. enter)
assert!(!co.has_immediate2());
assert_eq!(co.immediate_offset2(), 0);
assert_eq!(co.immediate_size2(), 0);