Add Register{Ext,Info}

This commit is contained in:
0xd4d 2020-12-09 21:30:43 +01:00
parent b73e2c5a73
commit 2b4c652879
11 changed files with 1251 additions and 4 deletions

View File

@ -139,4 +139,7 @@ test("RegisterExt funcs", () => {
expect(RegisterExt.isMM(Register.CL)).toBe(false);
expect(RegisterExt.isMM(Register.MM3)).toBe(true);
});
expect(RegisterExt.isTMM(Register.CL)).toBe(false);
expect(RegisterExt.isTMM(Register.TMM3)).toBe(true);
});

View File

@ -19,6 +19,8 @@ Welcome to iced-x86's documentation!
src/FpuStackIncrementInfo
src/MemorySizeExt
src/MemorySizeInfo
src/RegisterExt
src/RegisterInfo
src/UsedMemory
src/UsedRegister
:maxdepth: 2

View File

@ -0,0 +1,5 @@
RegisterExt
===========
.. autoclass:: iced_x86::RegisterExt
:members:

View File

@ -0,0 +1,5 @@
RegisterInfo
============
.. autoclass:: iced_x86::RegisterInfo
:members:

View File

@ -30,7 +30,8 @@ iced-x86 is a high performance and correct x86/x64 disassembler, assembler and i
from ._iced_x86_py import BlockEncoder, ConstantOffsets, Decoder, Encoder, FastFormatter, \
Formatter, FpuStackIncrementInfo, Instruction, InstructionInfo, \
InstructionInfoFactory, MemorySizeExt, MemorySizeInfo, OpCodeInfo, UsedMemory, UsedRegister
InstructionInfoFactory, MemorySizeExt, MemorySizeInfo, OpCodeInfo, RegisterExt, RegisterInfo, \
UsedMemory, UsedRegister
from . import CC_a
from . import CC_ae
@ -78,7 +79,11 @@ __all__ = [
"Instruction",
"InstructionInfo",
"InstructionInfoFactory",
"MemorySizeExt",
"MemorySizeInfo",
"OpCodeInfo",
"RegisterExt",
"RegisterInfo",
"UsedMemory",
"UsedRegister",
@ -106,8 +111,6 @@ __all__ = [
"FormatterSyntax",
"MandatoryPrefix",
"MemorySize",
"MemorySizeExt",
"MemorySizeInfo",
"MemorySizeOptions",
"Mnemonic",
"OpAccess",

View File

@ -1142,3 +1142,70 @@ class MemorySizeExt:
def element_count(memory_size: MemorySize) -> int: ...
@staticmethod
def is_broadcast(memory_size: MemorySize) -> bool: ...
class RegisterInfo:
def __init__(self, register: Register) -> None: ...
@property
def register(self) -> Register: ...
@property
def base(self) -> Register: ...
@property
def number(self) -> int: ...
@property
def full_register(self) -> Register: ...
@property
def full_register32(self) -> Register: ...
@property
def size(self) -> int: ...
class RegisterExt:
@staticmethod
def info(register: Register) -> RegisterInfo: ...
@staticmethod
def base(register: Register) -> Register: ...
@staticmethod
def number(register: Register) -> int: ...
@staticmethod
def full_register(register: Register) -> Register: ...
@staticmethod
def full_register32(register: Register) -> Register: ...
@staticmethod
def size(register: Register) -> int: ...
@staticmethod
def is_segment_register(register: Register) -> bool: ...
@staticmethod
def is_gpr(register: Register) -> bool: ...
@staticmethod
def is_gpr8(register: Register) -> bool: ...
@staticmethod
def is_gpr16(register: Register) -> bool: ...
@staticmethod
def is_gpr32(register: Register) -> bool: ...
@staticmethod
def is_gpr64(register: Register) -> bool: ...
@staticmethod
def is_xmm(register: Register) -> bool: ...
@staticmethod
def is_ymm(register: Register) -> bool: ...
@staticmethod
def is_zmm(register: Register) -> bool: ...
@staticmethod
def is_vector_register(register: Register) -> bool: ...
@staticmethod
def is_ip(register: Register) -> bool: ...
@staticmethod
def is_k(register: Register) -> bool: ...
@staticmethod
def is_cr(register: Register) -> bool: ...
@staticmethod
def is_dr(register: Register) -> bool: ...
@staticmethod
def is_tr(register: Register) -> bool: ...
@staticmethod
def is_st(register: Register) -> bool: ...
@staticmethod
def is_bnd(register: Register) -> bool: ...
@staticmethod
def is_mm(register: Register) -> bool: ...
@staticmethod
def is_tmm(register: Register) -> bool: ...

View File

@ -90,6 +90,8 @@ mod instruction;
mod memory_size_ext;
mod memory_size_info;
mod op_code_info;
mod register_ext;
mod register_info;
use block_encoder::BlockEncoder;
use constant_offsets::ConstantOffsets;
@ -103,6 +105,8 @@ use memory_size_ext::MemorySizeExt;
use memory_size_info::MemorySizeInfo;
use op_code_info::OpCodeInfo;
use pyo3::prelude::*;
use register_ext::RegisterExt;
use register_info::RegisterInfo;
#[pymodule]
fn _iced_x86_py(_py: Python, m: &PyModule) -> PyResult<()> {
@ -123,6 +127,8 @@ fn _iced_x86_py(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<MemorySizeExt>()?;
m.add_class::<MemorySizeInfo>()?;
m.add_class::<OpCodeInfo>()?;
m.add_class::<RegisterExt>()?;
m.add_class::<RegisterInfo>()?;
m.add_class::<UsedMemory>()?;
m.add_class::<UsedRegister>()?;

View File

@ -0,0 +1,687 @@
/*
Copyright (C) 2018-2019 de4dot@gmail.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
use crate::enum_utils::to_register;
use crate::register_info::RegisterInfo;
use pyo3::prelude::*;
#[pyclass(module = "_iced_x86_py")]
#[text_signature = "(/)"]
pub(crate) struct RegisterExt {}
/// :class:`Register` enum extension methods, see also :class:`RegisterInfo`
#[pymethods]
impl RegisterExt {
/// Gets register info
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// :class:`RegisterInfo`: Register info
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterExt.info(Register.EAX)
/// assert info.size == 4
#[staticmethod]
#[text_signature = "(register, /)"]
fn info(register: u32) -> PyResult<RegisterInfo> {
Ok(RegisterInfo { info: to_register(register)?.info() })
}
/// Gets the base register, eg. ``AL``, ``AX``, ``EAX``, ``RAX``, ``MM0``, ``XMM0``, ``YMM0``, ``ZMM0``, ``ES``
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// :class:`Register`: Base register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.base(Register.GS) == Register.ES
/// assert RegisterExt.base(Register.SIL) == Register.AL
/// assert RegisterExt.base(Register.SP) == Register.AX
/// assert RegisterExt.base(Register.R13D) == Register.EAX
/// assert RegisterExt.base(Register.RBP) == Register.RAX
/// assert RegisterExt.base(Register.MM6) == Register.MM0
/// assert RegisterExt.base(Register.XMM28) == Register.XMM0
/// assert RegisterExt.base(Register.YMM12) == Register.YMM0
/// assert RegisterExt.base(Register.ZMM31) == Register.ZMM0
/// assert RegisterExt.base(Register.K3) == Register.K0
/// assert RegisterExt.base(Register.BND1) == Register.BND0
/// assert RegisterExt.base(Register.ST7) == Register.ST0
/// assert RegisterExt.base(Register.CR8) == Register.CR0
/// assert RegisterExt.base(Register.DR6) == Register.DR0
/// assert RegisterExt.base(Register.TR3) == Register.TR0
/// assert RegisterExt.base(Register.RIP) == Register.EIP
#[staticmethod]
#[text_signature = "(register, /)"]
fn base(register: u32) -> PyResult<u32> {
Ok(to_register(register)?.base() as u32)
}
/// The register number (index) relative to :class:`RegisterExt.base`, eg. 0-15, or 0-31, or if 8-bit GPR, 0-19
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// int: Register number (index) relative to the base register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.number(Register.GS) == 5
/// assert RegisterExt.number(Register.SIL) == 10
/// assert RegisterExt.number(Register.SP) == 4
/// assert RegisterExt.number(Register.R13D) == 13
/// assert RegisterExt.number(Register.RBP) == 5
/// assert RegisterExt.number(Register.MM6) == 6
/// assert RegisterExt.number(Register.XMM28) == 28
/// assert RegisterExt.number(Register.YMM12) == 12
/// assert RegisterExt.number(Register.ZMM31) == 31
/// assert RegisterExt.number(Register.K3) == 3
/// assert RegisterExt.number(Register.BND1) == 1
/// assert RegisterExt.number(Register.ST7) == 7
/// assert RegisterExt.number(Register.CR8) == 8
/// assert RegisterExt.number(Register.DR6) == 6
/// assert RegisterExt.number(Register.TR3) == 3
/// assert RegisterExt.number(Register.RIP) == 1
#[staticmethod]
#[text_signature = "(register, /)"]
fn number(register: u32) -> PyResult<u32> {
Ok(to_register(register)?.number() as u32)
}
/// Gets the full register that this one is a part of, eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``RCX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11``
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// :class:`Register`: Full register (64-bit GPRs)
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.full_register(Register.GS) == Register.GS
/// assert RegisterExt.full_register(Register.SIL) == Register.RSI
/// assert RegisterExt.full_register(Register.SP) == Register.RSP
/// assert RegisterExt.full_register(Register.R13D) == Register.R13
/// assert RegisterExt.full_register(Register.RBP) == Register.RBP
/// assert RegisterExt.full_register(Register.MM6) == Register.MM6
/// assert RegisterExt.full_register(Register.XMM10) == Register.ZMM10
/// assert RegisterExt.full_register(Register.YMM10) == Register.ZMM10
/// assert RegisterExt.full_register(Register.ZMM10) == Register.ZMM10
/// assert RegisterExt.full_register(Register.K3) == Register.K3
/// assert RegisterExt.full_register(Register.BND1) == Register.BND1
/// assert RegisterExt.full_register(Register.ST7) == Register.ST7
/// assert RegisterExt.full_register(Register.CR8) == Register.CR8
/// assert RegisterExt.full_register(Register.DR6) == Register.DR6
/// assert RegisterExt.full_register(Register.TR3) == Register.TR3
/// assert RegisterExt.full_register(Register.RIP) == Register.RIP
#[staticmethod]
#[text_signature = "(register, /)"]
fn full_register(register: u32) -> PyResult<u32> {
Ok(to_register(register)?.full_register() as u32)
}
/// Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned,
/// eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``ECX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11``
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// :class:`Register`: Full register (32-bit GPRs)
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.full_register32(Register.GS) == Register.GS
/// assert RegisterExt.full_register32(Register.SIL) == Register.ESI
/// assert RegisterExt.full_register32(Register.SP) == Register.ESP
/// assert RegisterExt.full_register32(Register.R13D) == Register.R13D
/// assert RegisterExt.full_register32(Register.RBP) == Register.EBP
/// assert RegisterExt.full_register32(Register.MM6) == Register.MM6
/// assert RegisterExt.full_register32(Register.XMM10) == Register.ZMM10
/// assert RegisterExt.full_register32(Register.YMM10) == Register.ZMM10
/// assert RegisterExt.full_register32(Register.ZMM10) == Register.ZMM10
/// assert RegisterExt.full_register32(Register.K3) == Register.K3
/// assert RegisterExt.full_register32(Register.BND1) == Register.BND1
/// assert RegisterExt.full_register32(Register.ST7) == Register.ST7
/// assert RegisterExt.full_register32(Register.CR8) == Register.CR8
/// assert RegisterExt.full_register32(Register.DR6) == Register.DR6
/// assert RegisterExt.full_register32(Register.TR3) == Register.TR3
/// assert RegisterExt.full_register32(Register.RIP) == Register.RIP
#[staticmethod]
#[text_signature = "(register, /)"]
fn full_register32(register: u32) -> PyResult<u32> {
Ok(to_register(register)?.full_register32() as u32)
}
/// Gets the size of the register in bytes
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// int: Size of the register in bytes
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.size(Register.GS) == 2
/// assert RegisterExt.size(Register.SIL) == 1
/// assert RegisterExt.size(Register.SP) == 2
/// assert RegisterExt.size(Register.R13D) == 4
/// assert RegisterExt.size(Register.RBP) == 8
/// assert RegisterExt.size(Register.MM6) == 8
/// assert RegisterExt.size(Register.XMM10) == 16
/// assert RegisterExt.size(Register.YMM10) == 32
/// assert RegisterExt.size(Register.ZMM10) == 64
/// assert RegisterExt.size(Register.K3) == 8
/// assert RegisterExt.size(Register.BND1) == 16
/// assert RegisterExt.size(Register.ST7) == 10
/// assert RegisterExt.size(Register.CR8) == 8
/// assert RegisterExt.size(Register.DR6) == 8
/// assert RegisterExt.size(Register.TR3) == 4
/// assert RegisterExt.size(Register.RIP) == 8
#[staticmethod]
#[text_signature = "(register, /)"]
fn size(register: u32) -> PyResult<u32> {
Ok(to_register(register)?.size() as u32)
}
/// Checks if it's a segment register (``ES``, ``CS``, ``SS``, ``DS``, ``FS``, ``GS``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a segment register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.is_segment_register(Register.GS)
/// assert not RegisterExt.is_segment_register(Register.RCX)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_segment_register(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_segment_register())
}
/// Checks if it's a general purpose register (``AL``-``R15L``, ``AX``-``R15W``, ``EAX``-``R15D``, ``RAX``-``R15``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a general purpose register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_gpr(Register.GS)
/// assert RegisterExt.is_gpr(Register.CH)
/// assert RegisterExt.is_gpr(Register.DX)
/// assert RegisterExt.is_gpr(Register.R13D)
/// assert RegisterExt.is_gpr(Register.RSP)
/// assert not RegisterExt.is_gpr(Register.XMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_gpr(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_gpr())
}
/// Checks if it's an 8-bit general purpose register (``AL``-``R15L``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's an 8-bit general purpose register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_gpr8(Register.GS)
/// assert RegisterExt.is_gpr8(Register.CH)
/// assert not RegisterExt.is_gpr8(Register.DX)
/// assert not RegisterExt.is_gpr8(Register.R13D)
/// assert not RegisterExt.is_gpr8(Register.RSP)
/// assert not RegisterExt.is_gpr8(Register.XMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_gpr8(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_gpr8())
}
/// Checks if it's a 16-bit general purpose register (``AX``-``R15W``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a 16-bit general purpose register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_gpr16(Register.GS)
/// assert not RegisterExt.is_gpr16(Register.CH)
/// assert RegisterExt.is_gpr16(Register.DX)
/// assert not RegisterExt.is_gpr16(Register.R13D)
/// assert not RegisterExt.is_gpr16(Register.RSP)
/// assert not RegisterExt.is_gpr16(Register.XMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_gpr16(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_gpr16())
}
/// Checks if it's a 32-bit general purpose register (``EAX``-``R15D``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a 32-bit general purpose register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_gpr32(Register.GS)
/// assert not RegisterExt.is_gpr32(Register.CH)
/// assert not RegisterExt.is_gpr32(Register.DX)
/// assert RegisterExt.is_gpr32(Register.R13D)
/// assert not RegisterExt.is_gpr32(Register.RSP)
/// assert not RegisterExt.is_gpr32(Register.XMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_gpr32(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_gpr32())
}
/// Checks if it's a 64-bit general purpose register (``RAX``-``R15``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a 64-bit general purpose register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_gpr64(Register.GS)
/// assert not RegisterExt.is_gpr64(Register.CH)
/// assert not RegisterExt.is_gpr64(Register.DX)
/// assert not RegisterExt.is_gpr64(Register.R13D)
/// assert RegisterExt.is_gpr64(Register.RSP)
/// assert not RegisterExt.is_gpr64(Register.XMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_gpr64(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_gpr64())
}
/// Checks if it's a 128-bit vector register (``XMM0``-``XMM31``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's an XMM register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_xmm(Register.R13D)
/// assert not RegisterExt.is_xmm(Register.RSP)
/// assert RegisterExt.is_xmm(Register.XMM0)
/// assert not RegisterExt.is_xmm(Register.YMM0)
/// assert not RegisterExt.is_xmm(Register.ZMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_xmm(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_xmm())
}
/// Checks if it's a 256-bit vector register (``YMM0``-``YMM31``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a YMM register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_ymm(Register.R13D)
/// assert not RegisterExt.is_ymm(Register.RSP)
/// assert not RegisterExt.is_ymm(Register.XMM0)
/// assert RegisterExt.is_ymm(Register.YMM0)
/// assert not RegisterExt.is_ymm(Register.ZMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_ymm(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_ymm())
}
/// Checks if it's a 512-bit vector register (``ZMM0``-``ZMM31``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a ZMM register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_zmm(Register.R13D)
/// assert not RegisterExt.is_zmm(Register.RSP)
/// assert not RegisterExt.is_zmm(Register.XMM0)
/// assert not RegisterExt.is_zmm(Register.YMM0)
/// assert RegisterExt.is_zmm(Register.ZMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_zmm(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_zmm())
}
/// Checks if it's an ``XMM``, ``YMM`` or ``ZMM`` register
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a vector register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_vector_register(Register.R13D)
/// assert not RegisterExt.is_vector_register(Register.RSP)
/// assert RegisterExt.is_vector_register(Register.XMM0)
/// assert RegisterExt.is_vector_register(Register.YMM0)
/// assert RegisterExt.is_vector_register(Register.ZMM0)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_vector_register(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_vector_register())
}
/// Checks if it's ``EIP``/``RIP``
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's ``EIP``/``RIP``
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert RegisterExt.is_ip(Register.EIP)
/// assert RegisterExt.is_ip(Register.RIP)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_ip(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_ip())
}
/// Checks if it's an opmask register (``K0``-``K7``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's an opmask register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_k(Register.R13D)
/// assert RegisterExt.is_k(Register.K3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_k(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_k())
}
/// Checks if it's a control register (``CR0``-``CR15``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a control register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_cr(Register.R13D)
/// assert RegisterExt.is_cr(Register.CR3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_cr(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_cr())
}
/// Checks if it's a debug register (``DR0``-``DR15``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a debug register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_dr(Register.R13D)
/// assert RegisterExt.is_dr(Register.DR3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_dr(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_dr())
}
/// Checks if it's a test register (``TR0``-``TR7``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a test register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_tr(Register.R13D)
/// assert RegisterExt.is_tr(Register.TR3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_tr(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_tr())
}
/// Checks if it's an FPU stack register (``ST0``-``ST7``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's an FPU register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_st(Register.R13D)
/// assert RegisterExt.is_st(Register.ST3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_st(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_st())
}
/// Checks if it's a bound register (``BND0``-``BND3``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a bnd register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_bnd(Register.R13D)
/// assert RegisterExt.is_bnd(Register.BND3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_bnd(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_bnd())
}
/// Checks if it's an MMX register (``MM0``-``MM7``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's an mmx register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_mm(Register.R13D)
/// assert RegisterExt.is_mm(Register.MM3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_mm(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_mm())
}
/// Checks if it's a tile register (``TMM0``-``TMM7``)
///
/// Args:
/// `register` (:class:`Register`): Enum value
///
/// Returns:
/// bool: ``True`` if it's a tmm register
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// assert not RegisterExt.is_tmm(Register.R13D)
/// assert RegisterExt.is_tmm(Register.TMM3)
#[staticmethod]
#[text_signature = "(register, /)"]
fn is_tmm(register: u32) -> PyResult<bool> {
Ok(to_register(register)?.is_tmm())
}
}

View File

@ -0,0 +1,201 @@
/*
Copyright (C) 2018-2019 de4dot@gmail.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
use crate::enum_utils::to_register;
use pyo3::prelude::*;
/// :class:`Register` enum info, see also :class:`RegisterExt`
///
/// Args:
/// `register_size` (:class:`Register`): Enum value
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.number == 5
#[pyclass(module = "_iced_x86_py")]
#[text_signature = "(register_size, /)"]
pub(crate) struct RegisterInfo {
pub(crate) info: &'static iced_x86::RegisterInfo,
}
#[pymethods]
impl RegisterInfo {
#[new]
fn new(register: u32) -> PyResult<Self> {
Ok(RegisterInfo { info: to_register(register)?.info() })
}
/// :class:`Register`: Gets the register value passed into the constructor
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.EAX)
/// assert info.register == Register.EAX
#[getter]
fn register(&self) -> u32 {
self.info.register() as u32
}
/// :class:`Register`: Gets the base register, eg. ``AL``, ``AX``, ``EAX``, ``RAX``, ``MM0``, ``XMM0``, ``YMM0``, ``ZMM0``, ``ES``
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.base == Register.ES
/// info = RegisterInfo(Register.RDX)
/// assert info.base == Register.RAX
/// info = RegisterInfo(Register.XMM13)
/// assert info.base == Register.XMM0
/// info = RegisterInfo(Register.YMM13)
/// assert info.base == Register.YMM0
/// info = RegisterInfo(Register.ZMM13)
/// assert info.base == Register.ZMM0
#[getter]
fn base(&self) -> u32 {
self.info.base() as u32
}
/// int: The register number (index) relative to :class:`RegisterInfo.base`, eg. 0-15, or 0-31, or if 8-bit GPR, 0-19
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.number == 5
/// info = RegisterInfo(Register.RDX)
/// assert info.number == 2
/// info = RegisterInfo(Register.XMM13)
/// assert info.number == 13
/// info = RegisterInfo(Register.YMM13)
/// assert info.number == 13
/// info = RegisterInfo(Register.ZMM13)
/// assert info.number == 13
#[getter]
fn number(&self) -> u32 {
self.info.number() as u32
}
/// :class:`Register`: The full register that this one is a part of, eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``RCX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11``
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.full_register == Register.GS
/// info = RegisterInfo(Register.BH)
/// assert info.full_register == Register.RBX
/// info = RegisterInfo(Register.DX)
/// assert info.full_register == Register.RDX
/// info = RegisterInfo(Register.ESP)
/// assert info.full_register == Register.RSP
/// info = RegisterInfo(Register.RCX)
/// assert info.full_register == Register.RCX
/// info = RegisterInfo(Register.XMM3)
/// assert info.full_register == Register.ZMM3
/// info = RegisterInfo(Register.YMM3)
/// assert info.full_register == Register.ZMM3
/// info = RegisterInfo(Register.ZMM3)
/// assert info.full_register == Register.ZMM3
#[getter]
fn full_register(&self) -> u32 {
self.info.full_register() as u32
}
/// :class:`Register`: Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned,
/// eg. ``CL``/``CH``/``CX``/``ECX``/``RCX`` -> ``ECX``, ``XMM11``/``YMM11``/``ZMM11`` -> ``ZMM11``
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.full_register32 == Register.GS
/// info = RegisterInfo(Register.BH)
/// assert info.full_register32 == Register.EBX
/// info = RegisterInfo(Register.DX)
/// assert info.full_register32 == Register.EDX
/// info = RegisterInfo(Register.ESP)
/// assert info.full_register32 == Register.ESP
/// info = RegisterInfo(Register.RCX)
/// assert info.full_register32 == Register.ECX
/// info = RegisterInfo(Register.XMM3)
/// assert info.full_register32 == Register.ZMM3
/// info = RegisterInfo(Register.YMM3)
/// assert info.full_register32 == Register.ZMM3
/// info = RegisterInfo(Register.ZMM3)
/// assert info.full_register32 == Register.ZMM3
#[getter]
fn full_register32(&self) -> u32 {
self.info.full_register32() as u32
}
/// int: Size of the register in bytes
///
/// Examples:
///
/// .. testcode::
///
/// from iced_x86 import *
///
/// info = RegisterInfo(Register.GS)
/// assert info.size == 2
/// info = RegisterInfo(Register.BH)
/// assert info.size == 1
/// info = RegisterInfo(Register.DX)
/// assert info.size == 2
/// info = RegisterInfo(Register.ESP)
/// assert info.size == 4
/// info = RegisterInfo(Register.RCX)
/// assert info.size == 8
/// info = RegisterInfo(Register.XMM3)
/// assert info.size == 16
/// info = RegisterInfo(Register.YMM3)
/// assert info.size == 32
/// info = RegisterInfo(Register.ZMM3)
/// assert info.size == 64
#[getter]
fn size(&self) -> u32 {
self.info.size() as u32
}
}

View File

@ -0,0 +1,262 @@
#
# Copyright (C) 2018-2019 de4dot@gmail.com
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
import pytest
from iced_x86 import *
def test_register_ext():
assert RegisterExt.base(Register.DL) == Register.AL
assert RegisterExt.base(Register.R8W) == Register.AX
assert RegisterExt.base(Register.R15D) == Register.EAX
assert RegisterExt.base(Register.R13) == Register.RAX
assert RegisterExt.base(Register.FS) == Register.ES
assert RegisterExt.base(Register.XMM2) == Register.XMM0
assert RegisterExt.base(Register.YMM20) == Register.YMM0
assert RegisterExt.base(Register.ZMM31) == Register.ZMM0
assert RegisterExt.number(Register.DL) == 2
assert RegisterExt.number(Register.R15) == 15
assert RegisterExt.number(Register.YMM21) == 21
assert RegisterExt.full_register(Register.CL) == Register.RCX
assert RegisterExt.full_register(Register.DX) == Register.RDX
assert RegisterExt.full_register(Register.EBX) == Register.RBX
assert RegisterExt.full_register(Register.RSP) == Register.RSP
assert RegisterExt.full_register(Register.XMM2) == Register.ZMM2
assert RegisterExt.full_register(Register.YMM22) == Register.ZMM22
assert RegisterExt.full_register(Register.ZMM11) == Register.ZMM11
assert RegisterExt.full_register32(Register.CL) == Register.ECX
assert RegisterExt.full_register32(Register.DX) == Register.EDX
assert RegisterExt.full_register32(Register.EBX) == Register.EBX
assert RegisterExt.full_register32(Register.RSP) == Register.ESP
assert RegisterExt.full_register32(Register.XMM2) == Register.ZMM2
assert RegisterExt.full_register32(Register.YMM22) == Register.ZMM22
assert RegisterExt.full_register32(Register.ZMM11) == Register.ZMM11
assert RegisterExt.size(Register.DL) == 1
assert RegisterExt.size(Register.R8W) == 2
assert RegisterExt.size(Register.R15D) == 4
assert RegisterExt.size(Register.R13) == 8
assert RegisterExt.size(Register.FS) == 2
assert RegisterExt.size(Register.XMM2) == 16
assert RegisterExt.size(Register.YMM20) == 32
assert RegisterExt.size(Register.ZMM31) == 64
assert not RegisterExt.is_segment_register(Register.CX)
assert RegisterExt.is_segment_register(Register.GS)
assert RegisterExt.is_gpr(Register.CL)
assert RegisterExt.is_gpr(Register.DX)
assert RegisterExt.is_gpr(Register.ESP)
assert RegisterExt.is_gpr(Register.R15)
assert not RegisterExt.is_gpr(Register.ES)
assert RegisterExt.is_gpr8(Register.CL)
assert not RegisterExt.is_gpr8(Register.DX)
assert not RegisterExt.is_gpr8(Register.ESP)
assert not RegisterExt.is_gpr8(Register.R15)
assert not RegisterExt.is_gpr8(Register.ES)
assert not RegisterExt.is_gpr16(Register.CL)
assert RegisterExt.is_gpr16(Register.DX)
assert not RegisterExt.is_gpr16(Register.ESP)
assert not RegisterExt.is_gpr16(Register.R15)
assert not RegisterExt.is_gpr16(Register.ES)
assert not RegisterExt.is_gpr32(Register.CL)
assert not RegisterExt.is_gpr32(Register.DX)
assert RegisterExt.is_gpr32(Register.ESP)
assert not RegisterExt.is_gpr32(Register.R15)
assert not RegisterExt.is_gpr32(Register.ES)
assert not RegisterExt.is_gpr64(Register.CL)
assert not RegisterExt.is_gpr64(Register.DX)
assert not RegisterExt.is_gpr64(Register.ESP)
assert RegisterExt.is_gpr64(Register.R15)
assert not RegisterExt.is_gpr64(Register.ES)
assert not RegisterExt.is_vector_register(Register.CL)
assert RegisterExt.is_vector_register(Register.XMM1)
assert RegisterExt.is_vector_register(Register.YMM2)
assert RegisterExt.is_vector_register(Register.ZMM3)
assert not RegisterExt.is_xmm(Register.CL)
assert RegisterExt.is_xmm(Register.XMM1)
assert not RegisterExt.is_xmm(Register.YMM2)
assert not RegisterExt.is_xmm(Register.ZMM3)
assert not RegisterExt.is_ymm(Register.CL)
assert not RegisterExt.is_ymm(Register.XMM1)
assert RegisterExt.is_ymm(Register.YMM2)
assert not RegisterExt.is_ymm(Register.ZMM3)
assert not RegisterExt.is_zmm(Register.CL)
assert not RegisterExt.is_zmm(Register.XMM1)
assert not RegisterExt.is_zmm(Register.YMM2)
assert RegisterExt.is_zmm(Register.ZMM3)
assert not RegisterExt.is_ip(Register.CL)
assert RegisterExt.is_ip(Register.EIP)
assert RegisterExt.is_ip(Register.RIP)
assert not RegisterExt.is_k(Register.CL)
assert RegisterExt.is_k(Register.K3)
assert not RegisterExt.is_cr(Register.CL)
assert RegisterExt.is_cr(Register.CR3)
assert not RegisterExt.is_dr(Register.CL)
assert RegisterExt.is_dr(Register.DR3)
assert not RegisterExt.is_tr(Register.CL)
assert RegisterExt.is_tr(Register.TR3)
assert not RegisterExt.is_st(Register.CL)
assert RegisterExt.is_st(Register.ST3)
assert not RegisterExt.is_bnd(Register.CL)
assert RegisterExt.is_bnd(Register.BND3)
assert not RegisterExt.is_mm(Register.CL)
assert RegisterExt.is_mm(Register.MM3)
assert not RegisterExt.is_tmm(Register.CL)
assert RegisterExt.is_tmm(Register.TMM3)
@pytest.mark.parametrize("create", [
lambda register: RegisterExt.info(register),
lambda register: RegisterInfo(register),
])
def test_register_info(create):
info = create(Register.R10D)
assert info.register == Register.R10D
assert info.base == Register.EAX
assert info.number == 10
assert info.full_register == Register.R10
assert info.full_register32 == Register.R10D
assert info.size == 4
@pytest.mark.parametrize("create", [
lambda register: RegisterExt.info(register),
lambda register: RegisterInfo(register),
])
def test_register_invalid_arg(create):
with pytest.raises(ValueError):
create(1234)
def test_ext_base_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.base(1234)
def test_ext_number_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.number(1234)
def test_ext_full_register_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.full_register(1234)
def test_ext_full_register32_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.full_register32(1234)
def test_ext_size_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.size(1234)
def test_ext_is_segment_register_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_segment_register(1234)
def test_ext_is_gpr_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_gpr(1234)
def test_ext_is_gpr8_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_gpr8(1234)
def test_ext_is_gpr16_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_gpr16(1234)
def test_ext_is_gpr32_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_gpr32(1234)
def test_ext_is_gpr64_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_gpr64(1234)
def test_ext_is_xmm_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_xmm(1234)
def test_ext_is_ymm_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_ymm(1234)
def test_ext_is_zmm_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_zmm(1234)
def test_ext_is_vector_register_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_vector_register(1234)
def test_ext_is_ip_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_ip(1234)
def test_ext_is_k_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_k(1234)
def test_ext_is_cr_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_cr(1234)
def test_ext_is_dr_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_dr(1234)
def test_ext_is_tr_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_tr(1234)
def test_ext_is_st_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_st(1234)
def test_ext_is_bnd_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_bnd(1234)
def test_ext_is_mm_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_mm(1234)
def test_ext_is_tmm_invalid_arg():
with pytest.raises(ValueError):
RegisterExt.is_tmm(1234)

View File

@ -367,6 +367,8 @@ mod info {
/// The full register that this one is a part of, eg. `CL`/`CH`/`CX`/`ECX`/`RCX` -> `RCX`, `XMM11`/`YMM11`/`ZMM11` -> `ZMM11`
///
/// # Examples
///
/// ```
/// use iced_x86::*;
/// let info = Register::GS.info();
@ -395,6 +397,8 @@ mod info {
/// Gets the full register that this one is a part of, except if it's a GPR in which case the 32-bit register is returned,
/// eg. `CL`/`CH`/`CX`/`ECX`/`RCX` -> `ECX`, `XMM11`/`YMM11`/`ZMM11` -> `ZMM11`
///
/// # Examples
///
/// ```
/// use iced_x86::*;
/// let info = Register::GS.info();
@ -422,6 +426,8 @@ mod info {
/// Size of the register in bytes
///
/// # Examples
///
/// ```
/// use iced_x86::*;
/// let info = Register::GS.info();