libdasm import

git-svn-id: file:///home/svn/incoming/trunk@3358 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Matt Miller 2006-01-09 05:41:46 +00:00
parent eccdce049c
commit fd0d349eb7
7 changed files with 5054 additions and 0 deletions

View File

@ -0,0 +1,44 @@
module Ext
module Disassembler
module X86
require 'ext/disassembler/x86/dasm/dasm'
module Register
#
# Register number constants
#
EAX = AL = AX = ES = 0
ECX = CL = CX = CS = 1
EDX = DL = DX = SS = 2
EBX = BL = BX = DS = 3
ESP = AH = SP = FS = 4
EBP = CH = BP = GS = 5
ESI = DH = SI = 6
EDI = BH = DI = 7
module Type
General = 1
Segment = 2
Debug = 3
Control = 4
Test = 5
XMM = 6
MMX = 7
FPU = 8
end
end
module Operand
module Type
Memory = 1
Register = 2
Immediate = 3
end
end
end
end
end

View File

@ -0,0 +1,862 @@
//
// Wraps jt's libdasm in ruby classes that can be accessed through:
//
// Ext::Disassembler::X86::Dasm
// Ext::Disassembler::X86::Dasm::Instruction
// Ext::Disassembler::X86::Dasm::Operand
//
// Example:
//
// dasm = Ext::Disassembler::X86::Dasm.new
//
// dasm.disassemble(buf).each { |instruction|
// puts instruction.to_s
// }
//
// All credits for the disassembler to go jt <jt at klake.org> :)
//
// skape
// 01/2006
//
#include <stdlib.h>
#include <stdio.h>
#include <ruby.h>
#include "libdasm.h"
#define min(x, y) (x < y) ? x : y
static VALUE dasm_klass;
static VALUE instr_klass;
static VALUE instr_type_klass;
static VALUE oper_klass;
static VALUE oper_type_klass;
typedef struct _DASM_OBJECT
{
enum Mode mode;
enum Format format;
} DASM_OBJECT, *PDASM_OBJECT;
#define rb_dasm_cast(x, y) \
Data_Get_Struct(x, DASM_OBJECT, y)
////
//
// Operand class
//
////
typedef struct _OPERAND_OBJECT
{
OPERAND *op;
} OPERAND_OBJECT, *POPERAND_OBJECT;
#define rb_operand_cast(x, y) \
Data_Get_Struct(x, OPERAND_OBJECT, y)
//
// Deallocates the memory used by an instance of the operand class.
//
static void operand_free(void *oper)
{
if (oper)
free(oper);
}
//
// Allocates storage for the operand instance structure.
//
static VALUE operand_alloc(VALUE klass)
{
POPERAND_OBJECT oper;
VALUE obj;
obj = Data_Make_Struct(klass, OPERAND_OBJECT, 0, operand_free, oper);
oper->op = NULL;
return obj;
}
//
// Allocates and initializes an instance of the Operand class.
//
static VALUE operand_new(VALUE klass, OPERAND *op)
{
POPERAND_OBJECT oper;
VALUE obj = operand_alloc(klass);
rb_operand_cast(obj, oper);
oper->op = op;
return obj;
}
//
// Returns the operands type as one of the Ext::Disassembler::X86::Operand::Type
// constants.
//
static VALUE operand_type(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(get_operand_type(oper->op));
}
//
// Returns the register used by the operand, if any, as one of the
// Ext::Disassembler::X86::Register constants.
//
static VALUE operand_reg(VALUE self)
{
POPERAND_OBJECT oper;
VALUE rv;
rb_operand_cast(self, oper);
if (get_operand_register(oper->op) == REGISTER_NOP)
rv = Qnil;
else
rv = INT2FIX(get_operand_register(oper->op));
return rv;
}
//
// Returns the register type being used by the operand, if any, as one of the
// Ext::Disassembler::X86::Register::Type constants.
//
static VALUE operand_regtype(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(get_register_type(oper->op));
}
//
// Returns the base register that is used when the operand is a memory operand.
//
static VALUE operand_basereg(VALUE self)
{
POPERAND_OBJECT oper;
VALUE rv;
rb_operand_cast(self, oper);
return (oper->op->basereg == REGISTER_NOP) ? Qnil : INT2FIX(oper->op->basereg);
}
//
// Returns the index register that is used when the operand is a memory operand.
//
static VALUE operand_indexreg(VALUE self)
{
POPERAND_OBJECT oper;
VALUE rv;
rb_operand_cast(self, oper);
return (oper->op->indexreg == REGISTER_NOP) ? Qnil : INT2FIX(oper->op->indexreg);
}
//
// Returns the scale used.
//
static VALUE operand_scale(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(get_operand_scale(oper->op));
}
//
// The number of bytes used for displacement.
//
static VALUE operand_dispbytes(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->dispbytes);
}
//
// The offset from the start of the instruction for the displacement bytes.
//
static VALUE operand_dispoffset(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->dispoffset);
}
//
// The number of bytes used for immediate data.
//
static VALUE operand_immbytes(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->immbytes);
}
//
// The offset from the start of the instruction to the immediate bytes.
//
static VALUE operand_immoffset(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->immoffset);
}
//
// The number of bytes used for section.
//
static VALUE operand_sectionbytes(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->sectionbytes);
}
//
// The section being used.
//
static VALUE operand_section(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->section);
}
//
// The displacement value of the operand, if any.
//
static VALUE operand_displacement(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->displacement);
}
//
// The immediate value of the operand, if any.
//
static VALUE operand_immediate(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->immediate);
}
//
// Internal flags for the operand.
//
static VALUE operand_flags(VALUE self)
{
POPERAND_OBJECT oper;
rb_operand_cast(self, oper);
return INT2FIX(oper->op->flags);
}
////
//
// Instruction class
//
////
typedef struct _INSTRUCTION_OBJECT
{
INSTRUCTION inst;
BYTE raw[16];
VALUE dasm;
VALUE op1;
VALUE op2;
VALUE op3;
} INSTRUCTION_OBJECT, *PINSTRUCTION_OBJECT;
#define rb_instruction_cast(x, y) \
Data_Get_Struct(x, INSTRUCTION_OBJECT, y)
//
// Deallocates the memory used by an instance of the Instruction class.
//
static void instruction_free(void *inst)
{
if (inst)
free(inst);
}
//
// Allocates storage for the Instruction class.
//
static VALUE instruction_alloc(VALUE klass)
{
PINSTRUCTION_OBJECT inst;
VALUE obj;
obj = Data_Make_Struct(klass, INSTRUCTION_OBJECT, 0,
instruction_free, inst);
return obj;
}
//
// Creates and initializes an instance of the Instruction class based on the
// supplied INSTRUCTION instance passed from libdasm.
//
static VALUE instruction_new(VALUE klass, VALUE dasm, INSTRUCTION *raw_inst, BYTE *raw)
{
PINSTRUCTION_OBJECT inst;
VALUE obj = instruction_alloc(klass);
rb_instruction_cast(obj, inst);
inst->dasm = dasm;
memcpy(&inst->inst, raw_inst, sizeof(INSTRUCTION));
memcpy(inst->raw, raw, min(raw_inst->length, sizeof(inst->raw)));
inst->op1 = (raw_inst->op1.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op1);
inst->op2 = (raw_inst->op2.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op2);
inst->op3 = (raw_inst->op3.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op3);
return obj;
}
//
// Returns the length of the instruction in terms of bytes.
//
static VALUE instruction_length(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.length);
}
//
// Returns the type of instruction as represented by a constant that can be
// found under the Instruction::Type module.
//
static VALUE instruction_type(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.type);
}
//
// Returns the addressing mode used when disassembling this instruction.
//
static VALUE instruction_mode(VALUE self)
{
PINSTRUCTION_OBJECT inst;
VALUE rv;
rb_instruction_cast(self, inst);
switch (inst->inst.mode)
{
case MODE_32: rv = INT2FIX(32); break;
case MODE_16: rv = INT2FIX(16); break;
default: rv = Qnil; break;
}
return rv;
}
//
// Returns the one-byte opcode associated with this instruction.
//
static VALUE instruction_opcode(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return (inst->inst.opcode) ? CHR2FIX(inst->inst.opcode) : Qnil;
}
//
// Returns the Mod R/M byte of the instruction, if any.
//
static VALUE instruction_modrm(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return (inst->inst.modrm) ? CHR2FIX(inst->inst.modrm) : Qnil;
}
//
// Returns the SIB byte of the instruction, if any.
//
static VALUE instruction_sib(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return (inst->inst.sib) ? CHR2FIX(inst->inst.sib) : Qnil;
}
//
// Returns the number of displacement bytes used in the instruction.
//
static VALUE instruction_dispbytes(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.dispbytes);
}
//
// Returns the number of immediate bytes used by the instruction.
//
static VALUE instruction_immbytes(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.immbytes);
}
//
// Returns the number of section bytes used by the instruction.
//
static VALUE instruction_sectionbytes(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.sectionbytes);
}
//
// Arbitrary flags used by the disassembler.
//
static VALUE instruction_flags(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return INT2FIX(inst->inst.flags);
}
//
// Returns the raw string associated with the instruction.
//
static VALUE instruction_raw(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return rb_str_new(inst->raw, min(inst->inst.length, sizeof(inst->raw)));
}
//
// Converts the instruction to a printable disassembled string using the format
// that the Dasm instance the instruction came from is using.
//
static VALUE instruction_to_s(VALUE self)
{
PINSTRUCTION_OBJECT inst;
PDASM_OBJECT dasm;
char buf[32] = { 0 };
rb_instruction_cast(self, inst);
rb_dasm_cast(inst->dasm, dasm);
get_instruction_string(&inst->inst, dasm->format, 0, (BYTE *)buf, sizeof(buf) - 1);
return rb_str_new2(buf);
}
//
// Returns the first operand of the instruction, if any.
//
static VALUE instruction_op1(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return inst->op1;
}
//
// Returns the second operand of the instruction, if any.
//
static VALUE instruction_op2(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return inst->op2;
}
//
// Returns the third operand of the instruction, if any.
//
static VALUE instruction_op3(VALUE self)
{
PINSTRUCTION_OBJECT inst;
rb_instruction_cast(self, inst);
return inst->op3;
}
////
//
// Dasm class
//
////
//
// Deallocates the memory used by an instance of the Dasm class.
//
static void dasm_free(void *dasm)
{
if (dasm)
free(dasm);
}
//
// Initializes the underlying datastructure for an instance of the Dasm class.
//
static VALUE dasm_alloc(VALUE klass)
{
PDASM_OBJECT dasm;
VALUE obj;
obj = Data_Make_Struct(klass, DASM_OBJECT, 0, dasm_free, dasm);
dasm->mode = MODE_32;
dasm->format = FORMAT_INTEL;
return obj;
}
//
// Performs a disassembly on the supplied buffer and returns an array of
// Instruction instances.
//
static VALUE dasm_disassemble(VALUE self, VALUE buf)
{
PDASM_OBJECT obj;
INSTRUCTION inst;
VALUE instructions = rb_ary_new();
int offset = 0, len;
buf = StringValue(buf);
len = RSTRING(buf)->len;
rb_dasm_cast(self, obj);
while (offset < len)
{
VALUE rb_inst;
BYTE *current = (BYTE *)(RSTRING(buf)->ptr + offset);
if (!get_instruction(&inst, current, obj->mode))
break;
rb_inst = instruction_new(instr_klass, self, &inst, current);
rb_ary_push(instructions, rb_inst);
offset += inst.length;
}
return instructions;
}
//
// Sets the disassembler mode, either 16 or 32 bits.
//
static VALUE dasm_set_mode(VALUE self, VALUE bits)
{
PDASM_OBJECT obj;
int val = FIX2INT(bits);
rb_dasm_cast(self, obj);
switch (val)
{
case 32: obj->mode = MODE_32; break;
case 16: obj->mode = MODE_16; break;
default: rb_raise(rb_eArgError, "Invalid disassembler mode (must be 16 or 32)"); break;
}
return Qtrue;
}
//
// Returns the current disassembler mode that is being operated under.
//
static VALUE dasm_mode(VALUE self)
{
PDASM_OBJECT obj;
VALUE rv;
rb_dasm_cast(self, obj);
switch (obj->mode)
{
case MODE_32: rv = INT2FIX(32); break;
case MODE_16: rv = INT2FIX(16); break;
default: rv = Qnil; break;
}
return rv;
}
//
// Changes the format that should be used when displaying disassembly strings.
//
static VALUE dasm_set_format(VALUE self, VALUE format)
{
PDASM_OBJECT obj;
format = StringValue(format);
rb_dasm_cast(self, obj);
if (!strncasecmp(RSTRING(format)->ptr, "intel", 5))
obj->format = FORMAT_INTEL;
else if (!strncasecmp(RSTRING(format)->ptr, "att", 3))
obj->format = FORMAT_ATT;
else
rb_raise(rb_eArgError, "Invalid output format (must be intel or att)");
return Qnil;
}
//
// Returns the format currently being used when displaying string versions of
// instructions.
//
static VALUE dasm_format(VALUE self)
{
PDASM_OBJECT obj;
VALUE rv;
rb_dasm_cast(self, obj);
switch (obj->format)
{
case FORMAT_INTEL: rv = rb_str_new2("intel"); break;
case FORMAT_ATT: rv = rb_str_new2("att"); break;
default: rv = Qnil; break;
}
return rv;
}
//
// Initializes the dasm classes.
//
void Init_dasm()
{
// Dasm
dasm_klass = rb_define_class_under(
rb_define_module_under(
rb_define_module_under(
rb_define_module("Ext"),
"Disassembler"),
"X86"),
"Dasm",
rb_define_class("Dasm", rb_cObject));
rb_define_alloc_func(dasm_klass, dasm_alloc);
rb_define_method(dasm_klass, "disassemble", dasm_disassemble, 1);
rb_define_method(dasm_klass, "set_mode", dasm_set_mode, 1);
rb_define_method(dasm_klass, "mode", dasm_mode, 0);
rb_define_method(dasm_klass, "set_format", dasm_set_format, 1);
rb_define_method(dasm_klass, "format", dasm_format, 0);
// Instruction
instr_klass = rb_define_class_under(dasm_klass, "Instruction",
rb_define_class("Instruction", rb_cObject));
instr_type_klass = rb_define_module_under(instr_klass, "Type");
rb_define_const(instr_type_klass, "ASC", INT2FIX(INSTRUCTION_TYPE_ASC));
rb_define_const(instr_type_klass, "DCL", INT2FIX(INSTRUCTION_TYPE_DCL));
rb_define_const(instr_type_klass, "MOV", INT2FIX(INSTRUCTION_TYPE_MOV));
rb_define_const(instr_type_klass, "MOVSR", INT2FIX(INSTRUCTION_TYPE_MOVSR));
rb_define_const(instr_type_klass, "ADD", INT2FIX(INSTRUCTION_TYPE_ADD));
rb_define_const(instr_type_klass, "XADD", INT2FIX(INSTRUCTION_TYPE_XADD));
rb_define_const(instr_type_klass, "ADC", INT2FIX(INSTRUCTION_TYPE_ADC));
rb_define_const(instr_type_klass, "SUB", INT2FIX(INSTRUCTION_TYPE_SUB));
rb_define_const(instr_type_klass, "SBB", INT2FIX(INSTRUCTION_TYPE_SBB));
rb_define_const(instr_type_klass, "INC", INT2FIX(INSTRUCTION_TYPE_INC));
rb_define_const(instr_type_klass, "DEC", INT2FIX(INSTRUCTION_TYPE_DEC));
rb_define_const(instr_type_klass, "DIV", INT2FIX(INSTRUCTION_TYPE_DIV));
rb_define_const(instr_type_klass, "IDIV", INT2FIX(INSTRUCTION_TYPE_IDIV));
rb_define_const(instr_type_klass, "NOT", INT2FIX(INSTRUCTION_TYPE_NOT));
rb_define_const(instr_type_klass, "NEG", INT2FIX(INSTRUCTION_TYPE_NEG));
rb_define_const(instr_type_klass, "STOS", INT2FIX(INSTRUCTION_TYPE_STOS));
rb_define_const(instr_type_klass, "LODS", INT2FIX(INSTRUCTION_TYPE_LODS));
rb_define_const(instr_type_klass, "SCAS", INT2FIX(INSTRUCTION_TYPE_SCAS));
rb_define_const(instr_type_klass, "MOVS", INT2FIX(INSTRUCTION_TYPE_MOVS));
rb_define_const(instr_type_klass, "MOVSX", INT2FIX(INSTRUCTION_TYPE_MOVSX));
rb_define_const(instr_type_klass, "MOVZX", INT2FIX(INSTRUCTION_TYPE_MOVZX));
rb_define_const(instr_type_klass, "CMPS", INT2FIX(INSTRUCTION_TYPE_CMPS));
rb_define_const(instr_type_klass, "SHX", INT2FIX(INSTRUCTION_TYPE_SHX));
rb_define_const(instr_type_klass, "ROX", INT2FIX(INSTRUCTION_TYPE_ROX));
rb_define_const(instr_type_klass, "MUL", INT2FIX(INSTRUCTION_TYPE_MUL));
rb_define_const(instr_type_klass, "IMUL", INT2FIX(INSTRUCTION_TYPE_IMUL));
rb_define_const(instr_type_klass, "EIMUL", INT2FIX(INSTRUCTION_TYPE_EIMUL));
rb_define_const(instr_type_klass, "XOR", INT2FIX(INSTRUCTION_TYPE_XOR));
rb_define_const(instr_type_klass, "LEA", INT2FIX(INSTRUCTION_TYPE_LEA));
rb_define_const(instr_type_klass, "XCHG", INT2FIX(INSTRUCTION_TYPE_XCHG));
rb_define_const(instr_type_klass, "CMP", INT2FIX(INSTRUCTION_TYPE_CMP));
rb_define_const(instr_type_klass, "TEST", INT2FIX(INSTRUCTION_TYPE_TEST));
rb_define_const(instr_type_klass, "PUSH", INT2FIX(INSTRUCTION_TYPE_PUSH));
rb_define_const(instr_type_klass, "AND", INT2FIX(INSTRUCTION_TYPE_AND));
rb_define_const(instr_type_klass, "OR", INT2FIX(INSTRUCTION_TYPE_OR));
rb_define_const(instr_type_klass, "POP", INT2FIX(INSTRUCTION_TYPE_POP));
rb_define_const(instr_type_klass, "JMP", INT2FIX(INSTRUCTION_TYPE_JMP));
rb_define_const(instr_type_klass, "JMPC", INT2FIX(INSTRUCTION_TYPE_JMPC));
rb_define_const(instr_type_klass, "SETC", INT2FIX(INSTRUCTION_TYPE_SETC));
rb_define_const(instr_type_klass, "MOVC", INT2FIX(INSTRUCTION_TYPE_MOVC));
rb_define_const(instr_type_klass, "LOOP", INT2FIX(INSTRUCTION_TYPE_LOOP));
rb_define_const(instr_type_klass, "CALL", INT2FIX(INSTRUCTION_TYPE_CALL));
rb_define_const(instr_type_klass, "RET", INT2FIX(INSTRUCTION_TYPE_RET));
rb_define_const(instr_type_klass, "INT", INT2FIX(INSTRUCTION_TYPE_INT));
rb_define_const(instr_type_klass, "BT", INT2FIX(INSTRUCTION_TYPE_BT));
rb_define_const(instr_type_klass, "BTS", INT2FIX(INSTRUCTION_TYPE_BTS));
rb_define_const(instr_type_klass, "BTR", INT2FIX(INSTRUCTION_TYPE_BTR));
rb_define_const(instr_type_klass, "BTC", INT2FIX(INSTRUCTION_TYPE_BTC));
rb_define_const(instr_type_klass, "BSF", INT2FIX(INSTRUCTION_TYPE_BSF));
rb_define_const(instr_type_klass, "BSR", INT2FIX(INSTRUCTION_TYPE_BSR));
rb_define_const(instr_type_klass, "BSWAP", INT2FIX(INSTRUCTION_TYPE_BSWAP));
rb_define_const(instr_type_klass, "SGDT", INT2FIX(INSTRUCTION_TYPE_SGDT));
rb_define_const(instr_type_klass, "SIDT", INT2FIX(INSTRUCTION_TYPE_SIDT));
rb_define_const(instr_type_klass, "SLDT", INT2FIX(INSTRUCTION_TYPE_SLDT));
rb_define_const(instr_type_klass, "LFP", INT2FIX(INSTRUCTION_TYPE_LFP));
rb_define_const(instr_type_klass, "FCMOVC", INT2FIX(INSTRUCTION_TYPE_FCMOVC));
rb_define_const(instr_type_klass, "FADD", INT2FIX(INSTRUCTION_TYPE_FADD));
rb_define_const(instr_type_klass, "FADDP", INT2FIX(INSTRUCTION_TYPE_FADDP));
rb_define_const(instr_type_klass, "FIADD", INT2FIX(INSTRUCTION_TYPE_FIADD));
rb_define_const(instr_type_klass, "FSUB", INT2FIX(INSTRUCTION_TYPE_FSUB));
rb_define_const(instr_type_klass, "FSUBP", INT2FIX(INSTRUCTION_TYPE_FSUBP));
rb_define_const(instr_type_klass, "FISUB", INT2FIX(INSTRUCTION_TYPE_FISUB));
rb_define_const(instr_type_klass, "FSUBR", INT2FIX(INSTRUCTION_TYPE_FSUBR));
rb_define_const(instr_type_klass, "FSUBRP", INT2FIX(INSTRUCTION_TYPE_FSUBRP));
rb_define_const(instr_type_klass, "FISUBR", INT2FIX(INSTRUCTION_TYPE_FISUBR));
rb_define_const(instr_type_klass, "FMUL", INT2FIX(INSTRUCTION_TYPE_FMUL));
rb_define_const(instr_type_klass, "FMULP", INT2FIX(INSTRUCTION_TYPE_FMULP));
rb_define_const(instr_type_klass, "FIMUL", INT2FIX(INSTRUCTION_TYPE_FIMUL));
rb_define_const(instr_type_klass, "FDIV", INT2FIX(INSTRUCTION_TYPE_FDIV));
rb_define_const(instr_type_klass, "FDIVP", INT2FIX(INSTRUCTION_TYPE_FDIVP));
rb_define_const(instr_type_klass, "FDIVR", INT2FIX(INSTRUCTION_TYPE_FDIVR));
rb_define_const(instr_type_klass, "FDIVRP", INT2FIX(INSTRUCTION_TYPE_FDIVRP));
rb_define_const(instr_type_klass, "FIDIV", INT2FIX(INSTRUCTION_TYPE_FIDIV));
rb_define_const(instr_type_klass, "FIDIVR", INT2FIX(INSTRUCTION_TYPE_FIDIVR));
rb_define_const(instr_type_klass, "FCOM", INT2FIX(INSTRUCTION_TYPE_FCOM));
rb_define_const(instr_type_klass, "FCOMP", INT2FIX(INSTRUCTION_TYPE_FCOMP));
rb_define_const(instr_type_klass, "FCOMPP", INT2FIX(INSTRUCTION_TYPE_FCOMPP));
rb_define_const(instr_type_klass, "FCOMI", INT2FIX(INSTRUCTION_TYPE_FCOMI));
rb_define_const(instr_type_klass, "FCOMIP", INT2FIX(INSTRUCTION_TYPE_FCOMIP));
rb_define_const(instr_type_klass, "FUCOM", INT2FIX(INSTRUCTION_TYPE_FUCOM));
rb_define_const(instr_type_klass, "FUCOMP", INT2FIX(INSTRUCTION_TYPE_FUCOMP));
rb_define_const(instr_type_klass, "FUCOMPP", INT2FIX(INSTRUCTION_TYPE_FUCOMPP));
rb_define_const(instr_type_klass, "FUCOMI", INT2FIX(INSTRUCTION_TYPE_FUCOMI));
rb_define_const(instr_type_klass, "FUCOMIP", INT2FIX(INSTRUCTION_TYPE_FUCOMIP));
rb_define_const(instr_type_klass, "FST", INT2FIX(INSTRUCTION_TYPE_FST));
rb_define_const(instr_type_klass, "FSTP", INT2FIX(INSTRUCTION_TYPE_FSTP));
rb_define_const(instr_type_klass, "FIST", INT2FIX(INSTRUCTION_TYPE_FIST));
rb_define_const(instr_type_klass, "FISTP", INT2FIX(INSTRUCTION_TYPE_FISTP));
rb_define_const(instr_type_klass, "FISTTP", INT2FIX(INSTRUCTION_TYPE_FISTTP));
rb_define_const(instr_type_klass, "FLD", INT2FIX(INSTRUCTION_TYPE_FLD));
rb_define_const(instr_type_klass, "FILD", INT2FIX(INSTRUCTION_TYPE_FILD));
rb_define_const(instr_type_klass, "FICOM", INT2FIX(INSTRUCTION_TYPE_FICOM));
rb_define_const(instr_type_klass, "FICOMP", INT2FIX(INSTRUCTION_TYPE_FICOMP));
rb_define_const(instr_type_klass, "FFREE", INT2FIX(INSTRUCTION_TYPE_FFREE));
rb_define_const(instr_type_klass, "FFREEP", INT2FIX(INSTRUCTION_TYPE_FFREEP));
rb_define_const(instr_type_klass, "FXCH", INT2FIX(INSTRUCTION_TYPE_FXCH));
rb_define_const(instr_type_klass, "FPU", INT2FIX(INSTRUCTION_TYPE_FPU));
rb_define_const(instr_type_klass, "MMX", INT2FIX(INSTRUCTION_TYPE_MMX));
rb_define_const(instr_type_klass, "SSE", INT2FIX(INSTRUCTION_TYPE_SSE));
rb_define_const(instr_type_klass, "OTHER", INT2FIX(INSTRUCTION_TYPE_OTHER));
rb_define_const(instr_type_klass, "PRIV", INT2FIX(INSTRUCTION_TYPE_PRIV));
rb_define_alloc_func(instr_klass, instruction_alloc);
rb_define_method(instr_klass, "length", instruction_length, 0);
rb_define_method(instr_klass, "type", instruction_type, 0);
rb_define_method(instr_klass, "mode", instruction_mode, 0);
rb_define_method(instr_klass, "opcode", instruction_opcode, 0);
rb_define_method(instr_klass, "modrm", instruction_modrm, 0);
rb_define_method(instr_klass, "sib", instruction_sib, 0);
rb_define_method(instr_klass, "dispbytes", instruction_dispbytes, 0);
rb_define_method(instr_klass, "immbytes", instruction_immbytes, 0);
rb_define_method(instr_klass, "sectionbytes", instruction_sectionbytes, 0);
rb_define_method(instr_klass, "flags", instruction_flags, 0);
rb_define_method(instr_klass, "raw", instruction_raw, 0);
rb_define_method(instr_klass, "to_s", instruction_to_s, 0);
rb_define_method(instr_klass, "op1", instruction_op1, 0);
rb_define_method(instr_klass, "op2", instruction_op2, 0);
rb_define_method(instr_klass, "op3", instruction_op3, 0);
// Operand
oper_klass = rb_define_class_under(dasm_klass, "Operand",
rb_define_class("Operand", rb_cObject));
oper_type_klass = rb_define_module_under(oper_klass, "Type");
rb_define_alloc_func(oper_klass, operand_alloc);
rb_define_method(oper_klass, "type", operand_type, 0);
rb_define_method(oper_klass, "reg", operand_reg, 0);
rb_define_method(oper_klass, "regtype", operand_regtype, 0);
rb_define_method(oper_klass, "basereg", operand_basereg, 0);
rb_define_method(oper_klass, "indexreg", operand_indexreg, 0);
rb_define_method(oper_klass, "scale", operand_scale, 0);
rb_define_method(oper_klass, "dispbytes", operand_dispbytes, 0);
rb_define_method(oper_klass, "dispoffset", operand_dispoffset, 0);
rb_define_method(oper_klass, "immbytes", operand_immbytes, 0);
rb_define_method(oper_klass, "immoffset", operand_immoffset, 0);
rb_define_method(oper_klass, "sectionbytes", operand_sectionbytes, 0);
rb_define_method(oper_klass, "section", operand_section, 0);
rb_define_method(oper_klass, "displacement", operand_displacement, 0);
rb_define_method(oper_klass, "immediate", operand_immediate, 0);
rb_define_method(oper_klass, "flags", operand_flags, 0);
}

View File

@ -0,0 +1,77 @@
#!/usr/bin/env ruby
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..'))
require 'test/unit'
require 'ext/disassembler/x86'
require 'ext/disassembler/x86/dasm'
class Ext::Disassembler::X86::Dasm::UnitTest < Test::Unit::TestCase
Klass = Ext::Disassembler::X86::Dasm
def test_mode
d = Klass.new
assert_equal(32, d.mode)
assert_equal(true, d.set_mode(16))
assert_equal(16, d.mode)
assert_equal(true, d.set_mode(32))
assert_equal(32, d.mode)
end
def test_disassemble
d = Klass.new
b1 = "\x41"
ary = d.disassemble(b1)
assert_not_nil(ary)
inst = ary[0]
assert_not_nil(inst)
assert_kind_of(Ext::Disassembler::X86::Dasm::Instruction, inst)
assert_equal(1, inst.length)
assert_equal(Klass::Instruction::Type::INC, inst.type)
assert_equal(32, inst.mode)
assert_equal(0x41, inst.opcode)
assert_nil(inst.modrm)
assert_nil(inst.sib)
assert_equal(0, inst.dispbytes)
assert_equal(0, inst.immbytes)
assert_equal(0, inst.sectionbytes)
assert_equal("\x41", inst.raw)
assert_equal("inc ecx", inst.to_s);
d.set_format("att")
assert_equal("inc %ecx", inst.to_s);
end
def test_operand
d = Klass.new
b1 = "\xc7\x44\x24\x04\x78\x56\x34\x12\x41"
ary = d.disassemble(b1)
assert_not_nil(ary)
inst1 = ary[0]
inst2 = ary[1]
# inst1: mov dword [esp+0x4],0x12345678
assert_not_nil(inst1.op1)
assert_not_nil(inst1.op2)
assert_nil(inst1.op3)
assert_equal(Ext::Disassembler::X86::Operand::Type::Memory, inst1.op1.type)
assert_equal(Ext::Disassembler::X86::Operand::Type::Immediate, inst1.op2.type)
assert_equal(Ext::Disassembler::X86::Register::ESP, inst1.op1.basereg)
assert_equal(4, inst1.op1.displacement)
assert_equal(0x12345678, inst1.op2.immediate)
assert_equal("mov dword [esp+0x4],0x12345678", inst1.to_s)
# inst2: inc ecx
assert_not_nil(inst2.op1)
assert_nil(inst2.op2)
assert_nil(inst2.op3)
assert_equal(Ext::Disassembler::X86::Register::ECX, inst2.op1.reg)
assert_equal(Ext::Disassembler::X86::Register::Type::General, inst2.op1.regtype)
end
end

View File

@ -0,0 +1,2 @@
require 'mkmf'
create_makefile('dasm')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
/*
* libdasm -- simple x86 disassembly library
* (c) 2004 - 2005 jt / nologin.org
*
* libdasm.h:
* Definitions for structures, functions and other weird stuff
*
*/
#ifndef _LIBDASM_H
#define _LIBDASM_H
#ifdef __cplusplus
extern "C" {
#endif
#define __LIBDASM_VERSION__ 0x01030000
#define GET_VERSION_MAJOR \
(__LIBDASM_VERSION__ & 0xff000000) >> 24
#define GET_VERSION_MINOR1 \
(__LIBDASM_VERSION__ & 0x00ff0000) >> 16
#define GET_VERSION_MINOR2 \
(__LIBDASM_VERSION__ & 0x0000ff00) >> 8
#define GET_VERSION_MINOR3 \
(__LIBDASM_VERSION__ & 0x000000ff)
// Data types
#if _WIN32
#include <windows.h>
#define __inline__ __inline
#define snprintf _snprintf
typedef unsigned __int64 QWORD; // for MSVC
typedef signed __int8 SBYTE;
typedef signed __int16 SWORD;
typedef signed __int32 SDWORD;
typedef signed __int64 SQWORD;
#else
#if defined __sun
#define BYTE_ORDER 1234
#define BIG_ENDIAN 1234
#define LITTLE_ENDIAN 4321
#define u_int8_t uint8_t
#define u_int16_t uint16_t
#define u_int32_t uint32_t
#define u_int64_t uint64_t
#endif // other *nix
#include <sys/types.h>
typedef u_int8_t BYTE;
typedef u_int16_t WORD;
typedef u_int32_t DWORD;
typedef u_int64_t QWORD;
typedef int8_t SBYTE;
typedef int16_t SWORD;
typedef int32_t SDWORD;
typedef int64_t SQWORD;
#endif
// Define endianess
#ifndef __X86__
// These should catch x86 with most compilers
#if defined _X86_ || defined _i386_ || defined __i386__
#define __X86__
#endif
#endif
#ifndef __LITTLE_ENDIAN__
// These should catch little-endian with most compilers
#if (BYTE_ORDER == LITTLE_ENDIAN) || defined __X86__ || defined _ALPHA_
#define __LITTLE_ENDIAN__
#endif
#endif
// Registers
#define REGISTER_EAX 0
#define REGISTER_ECX 1
#define REGISTER_EDX 2
#define REGISTER_EBX 3
#define REGISTER_ESP 4
#define REGISTER_EBP 5
#define REGISTER_ESI 6
#define REGISTER_EDI 7
#define REGISTER_NOP 8 // no register defined
// Registers
#define REG_EAX REGISTER_EAX
#define REG_AX REG_EAX
#define REG_AL REG_EAX
#define REG_ES REG_EAX // Just for reg_table consistence
#define REG_ST0 REG_EAX // Just for reg_table consistence
#define REG_ECX REGISTER_ECX
#define REG_CX REG_ECX
#define REG_CL REG_ECX
#define REG_CS REG_ECX
#define REG_ST1 REG_ECX
#define REG_EDX REGISTER_EDX
#define REG_DX REG_EDX
#define REG_DL REG_EDX
#define REG_SS REG_EDX
#define REG_ST2 REG_EDX
#define REG_EBX REGISTER_EBX
#define REG_BX REG_EBX
#define REG_BL REG_EBX
#define REG_DS REG_EBX
#define REG_ST3 REG_EBX
#define REG_ESP REGISTER_ESP
#define REG_SP REG_ESP
#define REG_AH REG_ESP // Just for reg_table consistence
#define REG_FS REG_ESP
#define REG_ST4 REG_ESP
#define REG_EBP REGISTER_EBP
#define REG_BP REG_EBP
#define REG_CH REG_EBP
#define REG_GS REG_EBP
#define REG_ST5 REG_EBP
#define REG_ESI REGISTER_ESI
#define REG_SI REG_ESI
#define REG_DH REG_ESI
#define REG_ST6 REG_ESI
#define REG_EDI REGISTER_EDI
#define REG_DI REG_EDI
#define REG_BH REG_EDI
#define REG_ST7 REG_EDI
#define REG_NOP REGISTER_NOP
// Register types
#define REGISTER_TYPE_GEN 1
#define REGISTER_TYPE_SEGMENT 2
#define REGISTER_TYPE_DEBUG 3
#define REGISTER_TYPE_CONTROL 4
#define REGISTER_TYPE_TEST 5
#define REGISTER_TYPE_XMM 6
#define REGISTER_TYPE_MMX 7
#define REGISTER_TYPE_FPU 8
// Disassembling mode
enum Mode {
MODE_32, // 32-bit
MODE_16 // 16-bit
};
// Disassembling format
enum Format {
FORMAT_ATT,
FORMAT_INTEL,
};
// Instruction types (just the most common ones atm)
enum Instruction {
// Integer instructions
INSTRUCTION_TYPE_ASC, // aaa, aam, etc.
INSTRUCTION_TYPE_DCL, // daa, das
INSTRUCTION_TYPE_MOV,
INSTRUCTION_TYPE_MOVSR, // segment register
INSTRUCTION_TYPE_ADD,
INSTRUCTION_TYPE_XADD,
INSTRUCTION_TYPE_ADC,
INSTRUCTION_TYPE_SUB,
INSTRUCTION_TYPE_SBB,
INSTRUCTION_TYPE_INC,
INSTRUCTION_TYPE_DEC,
INSTRUCTION_TYPE_DIV,
INSTRUCTION_TYPE_IDIV,
INSTRUCTION_TYPE_NOT,
INSTRUCTION_TYPE_NEG,
INSTRUCTION_TYPE_STOS,
INSTRUCTION_TYPE_LODS,
INSTRUCTION_TYPE_SCAS,
INSTRUCTION_TYPE_MOVS,
INSTRUCTION_TYPE_MOVSX,
INSTRUCTION_TYPE_MOVZX,
INSTRUCTION_TYPE_CMPS,
INSTRUCTION_TYPE_SHX, // signed/unsigned shift left/right
INSTRUCTION_TYPE_ROX, // signed/unsigned rot left/right
INSTRUCTION_TYPE_MUL,
INSTRUCTION_TYPE_IMUL,
INSTRUCTION_TYPE_EIMUL, // "extended" imul with 2-3 operands
INSTRUCTION_TYPE_XOR,
INSTRUCTION_TYPE_LEA,
INSTRUCTION_TYPE_XCHG,
INSTRUCTION_TYPE_CMP,
INSTRUCTION_TYPE_TEST,
INSTRUCTION_TYPE_PUSH,
INSTRUCTION_TYPE_AND,
INSTRUCTION_TYPE_OR,
INSTRUCTION_TYPE_POP,
INSTRUCTION_TYPE_JMP,
INSTRUCTION_TYPE_JMPC, // conditional jump
INSTRUCTION_TYPE_SETC, // conditional byte set
INSTRUCTION_TYPE_MOVC, // conditional mov
INSTRUCTION_TYPE_LOOP,
INSTRUCTION_TYPE_CALL,
INSTRUCTION_TYPE_RET,
INSTRUCTION_TYPE_INT, // interrupt
INSTRUCTION_TYPE_BT, // bit tests
INSTRUCTION_TYPE_BTS,
INSTRUCTION_TYPE_BTR,
INSTRUCTION_TYPE_BTC,
INSTRUCTION_TYPE_BSF,
INSTRUCTION_TYPE_BSR,
INSTRUCTION_TYPE_BSWAP,
INSTRUCTION_TYPE_SGDT,
INSTRUCTION_TYPE_SIDT,
INSTRUCTION_TYPE_SLDT,
INSTRUCTION_TYPE_LFP,
// FPU instructions
INSTRUCTION_TYPE_FCMOVC, // float conditional mov
INSTRUCTION_TYPE_FADD,
INSTRUCTION_TYPE_FADDP,
INSTRUCTION_TYPE_FIADD,
INSTRUCTION_TYPE_FSUB,
INSTRUCTION_TYPE_FSUBP,
INSTRUCTION_TYPE_FISUB,
INSTRUCTION_TYPE_FSUBR,
INSTRUCTION_TYPE_FSUBRP,
INSTRUCTION_TYPE_FISUBR,
INSTRUCTION_TYPE_FMUL,
INSTRUCTION_TYPE_FMULP,
INSTRUCTION_TYPE_FIMUL,
INSTRUCTION_TYPE_FDIV,
INSTRUCTION_TYPE_FDIVP,
INSTRUCTION_TYPE_FDIVR,
INSTRUCTION_TYPE_FDIVRP,
INSTRUCTION_TYPE_FIDIV,
INSTRUCTION_TYPE_FIDIVR,
INSTRUCTION_TYPE_FCOM,
INSTRUCTION_TYPE_FCOMP,
INSTRUCTION_TYPE_FCOMPP,
INSTRUCTION_TYPE_FCOMI,
INSTRUCTION_TYPE_FCOMIP,
INSTRUCTION_TYPE_FUCOM,
INSTRUCTION_TYPE_FUCOMP,
INSTRUCTION_TYPE_FUCOMPP,
INSTRUCTION_TYPE_FUCOMI,
INSTRUCTION_TYPE_FUCOMIP,
INSTRUCTION_TYPE_FST,
INSTRUCTION_TYPE_FSTP,
INSTRUCTION_TYPE_FIST,
INSTRUCTION_TYPE_FISTP,
INSTRUCTION_TYPE_FISTTP,
INSTRUCTION_TYPE_FLD,
INSTRUCTION_TYPE_FILD,
INSTRUCTION_TYPE_FICOM,
INSTRUCTION_TYPE_FICOMP,
INSTRUCTION_TYPE_FFREE,
INSTRUCTION_TYPE_FFREEP,
INSTRUCTION_TYPE_FXCH,
INSTRUCTION_TYPE_FPU, // Other FPU instructions
INSTRUCTION_TYPE_MMX, // Other MMX instructions
INSTRUCTION_TYPE_SSE, // Other SSE instructions
INSTRUCTION_TYPE_OTHER, // Other instructions :-)
INSTRUCTION_TYPE_PRIV // Privileged instruction
};
// Operand types
enum Operand {
OPERAND_TYPE_NONE, // operand not present
OPERAND_TYPE_MEMORY, // memory operand ([eax], [0], etc.)
OPERAND_TYPE_REGISTER, // register operand (eax, mm0, etc.)
OPERAND_TYPE_IMMEDIATE, // immediate operand (0x1234)
};
// Structure definitions
// struct INST is used internally by the library
typedef struct _INST {
DWORD type; // Instruction type and flags
const char *mnemonic; // Instruction mnemonic
int flags1; // First operand flags (if any)
int flags2; // Second operand flags (if any)
int flags3; // Additional operand flags (if any)
int modrm; // Is MODRM byte present?
} INST, *PINST;
// Operands for the instruction
typedef struct _OPERAND {
enum Operand type; // Operand type (register, memory, etc)
int reg; // Register (if any)
int basereg; // Base register (if any)
int indexreg; // Index register (if any)
int scale; // Scale (if any)
int dispbytes; // Displacement bytes (0 = no displacement)
int dispoffset; // Displacement value offset
int immbytes; // Immediate bytes (0 = no immediate)
int immoffset; // Immediate value offset
int sectionbytes; // Section prefix bytes (0 = no section prefix)
WORD section; // Section prefix value
DWORD displacement; // Displacement value
DWORD immediate; // Immediate value
int flags; // Operand flags
} OPERAND, *POPERAND;
// struct INSTRUCTION is used to interface the library
typedef struct _INSTRUCTION {
int length; // Instruction length
enum Instruction type; // Instruction type
enum Mode mode; // Addressing mode
BYTE opcode; // Actual opcode
BYTE modrm; // MODRM byte
BYTE sib; // SIB byte
int extindex; // Extension table index
int fpuindex; // FPU table index
int dispbytes; // Displacement bytes (0 = no displacement)
int immbytes; // Immediate bytes (0 = no immediate)
int sectionbytes; // Section prefix bytes (0 = no section prefix)
OPERAND op1; // First operand (if any)
OPERAND op2; // Second operand (if any)
OPERAND op3; // Additional operand (if any)
PINST ptr; // Pointer to instruction table
int flags; // Instruction flags
} INSTRUCTION, *PINSTRUCTION;
// Function definitions
int get_instruction(
INSTRUCTION *inst, // pointer to INSTRUCTION structure
BYTE *addr, // code buffer
enum Mode mode // mode: MODE_32 or MODE_16
);
// Get complete instruction string
int get_instruction_string(
INSTRUCTION *inst, // pointer to INSTRUCTION structure
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
DWORD offset, // instruction absolute address
char *string, // string buffer
int length // string length
);
// Get mnemonic string
int get_mnemonic_string(
INSTRUCTION *inst, // pointer to INSTRUCTION structure
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
char *string, // string buffer
int length // string length
);
// Get individual operand string
int get_operand_string(
INSTRUCTION *inst, // pointer to INSTRUCTION structure
POPERAND op, // pointer to OPERAND structure
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
DWORD offset, // instruction absolute address
char *string, // string buffer
int length // string length
);
// Helper functions
int get_register_type(
POPERAND op
);
int get_operand_type(
POPERAND op
);
int get_operand_register(
POPERAND op
);
int get_operand_basereg(
POPERAND op
);
int get_operand_indexreg(
POPERAND op
);
int get_operand_scale(
POPERAND op
);
int get_operand_immediate(
POPERAND op,
DWORD *imm // returned immediate value
);
int get_operand_displacement(
POPERAND op,
DWORD *disp // returned displacement value
);
POPERAND get_source_operand(
PINSTRUCTION inst
);
POPERAND get_destination_operand(
PINSTRUCTION inst
);
// Instruction flags (prefixes)
// Group 1
#define MASK_PREFIX_G1(x) ((x) & 0xff000000) >> 24
#define PREFIX_LOCK 0x01000000 // 0xf0
#define PREFIX_REPNE 0x02000000 // 0xf2
#define PREFIX_REP 0x03000000 // 0xf3
#define PREFIX_REPE 0x03000000 // 0xf3
// Group 2
#define MASK_PREFIX_G2(x) ((x) & 0x00ff0000) >> 16
#define PREFIX_ES_OVERRIDE 0x00010000 // 0x26
#define PREFIX_CS_OVERRIDE 0x00020000 // 0x2e
#define PREFIX_SS_OVERRIDE 0x00030000 // 0x36
#define PREFIX_DS_OVERRIDE 0x00040000 // 0x3e
#define PREFIX_FS_OVERRIDE 0x00050000 // 0x64
#define PREFIX_GS_OVERRIDE 0x00060000 // 0x65
// Group 3 & 4
#define MASK_PREFIX_G3(x) ((x) & 0x0000ff00) >> 8
#define MASK_PREFIX_OPERAND(x) ((x) & 0x00000f00) >> 8
#define MASK_PREFIX_ADDR(x) ((x) & 0x0000f000) >> 12
#define PREFIX_OPERAND_SIZE_OVERRIDE 0x00000100 // 0x66
#define PREFIX_ADDR_SIZE_OVERRIDE 0x00001000 // 0x67
// Extensions
#define MASK_EXT(x) ((x) & 0x000000ff)
#define EXT_G1_1 0x00000001
#define EXT_G1_2 0x00000002
#define EXT_G1_3 0x00000003
#define EXT_G2_1 0x00000004
#define EXT_G2_2 0x00000005
#define EXT_G2_3 0x00000006
#define EXT_G2_4 0x00000007
#define EXT_G2_5 0x00000008
#define EXT_G2_6 0x00000009
#define EXT_G3_1 0x0000000a
#define EXT_G3_2 0x0000000b
#define EXT_G4 0x0000000c
#define EXT_G5 0x0000000d
#define EXT_G6 0x0000000e
#define EXT_G7 0x0000000f
#define EXT_G8 0x00000010
#define EXT_G9 0x00000011
#define EXT_GA 0x00000012
#define EXT_GB 0x00000013
#define EXT_GC 0x00000014
#define EXT_GD 0x00000015
#define EXT_GE 0x00000016
#define EXT_GF 0x00000017
#define EXT_G0 0x00000018
// Extra groups for 2 and 3-byte opcodes, and FPU stuff
#define EXT_T2 0x00000020 // opcode table 2
#define EXT_CP 0x00000030 // co-processor
// Instruction type flags
#define TYPE_3 0x80000000
#define MASK_TYPE_FLAGS(x) ((x) & 0xff000000)
#define MASK_TYPE_VALUE(x) ((x) & 0x00ffffff)
// Operand flags
#define FLAGS_NONE 0
// Operand Addressing Methods, from the Intel manual
#define MASK_AM(x) ((x) & 0x00ff0000)
#define AM_A 0x00010000 // Direct address with segment prefix
#define AM_C 0x00020000 // MODRM reg field defines control register
#define AM_D 0x00030000 // MODRM reg field defines debug register
#define AM_E 0x00040000 // MODRM byte defines reg/memory address
#define AM_G 0x00050000 // MODRM byte defines general-purpose reg
#define AM_I 0x00060000 // Immediate data follows
#define AM_J 0x00070000 // Immediate value is relative to EIP
#define AM_M 0x00080000 // MODRM mod field can refer only to memory
#define AM_O 0x00090000 // Displacement follows (without modrm/sib)
#define AM_P 0x000a0000 // MODRM reg field defines MMX register
#define AM_Q 0x000b0000 // MODRM defines MMX register or memory
#define AM_R 0x000c0000 // MODRM mod field can only refer to register
#define AM_S 0x000d0000 // MODRM reg field defines segment register
#define AM_T 0x000e0000 // MODRM reg field defines test register
#define AM_V 0x000f0000 // MODRM reg field defines XMM register
#define AM_W 0x00100000 // MODRM defines XMM register or memory
// Extra addressing modes used in this implementation
#define AM_I1 0x00200000 // Immediate byte 1 encoded in instruction
#define AM_REG 0x00210000 // Register encoded in instruction
#define AM_IND 0x00220000 // Register indirect encoded in instruction
// Operand Types, from the intel manual
#define MASK_OT(x) ((x) & 0xff000000)
#define OT_a 0x01000000
#define OT_b 0x02000000 // always 1 byte
#define OT_c 0x03000000 // byte or word, depending on operand
#define OT_d 0x04000000 // double-word
#define OT_q 0x05000000 // quad-word
#define OT_dq 0x06000000 // double quad-word
#define OT_v 0x07000000 // word or double-word, depending on operand
#define OT_w 0x08000000 // always word
#define OT_p 0x09000000 // 32-bit or 48-bit pointer
#define OT_pi 0x0a000000 // quadword MMX register
#define OT_pd 0x0b000000 // 128-bit double-precision float
#define OT_ps 0x0c000000 // 128-bit single-precision float
#define OT_s 0x0d000000 // 6-byte pseudo descriptor
#define OT_sd 0x0e000000 // Scalar of 128-bit double-precision float
#define OT_ss 0x0f000000 // Scalar of 128-bit single-precision float
#define OT_si 0x10000000 // Doubleword integer register
#define OT_t 0x11000000 // 80-bit packed FP data
// Operand permissions
#define MASK_PERMS(x) ((x) & 0x0000f000)
#define P_r 0x00004000 // Read
#define P_w 0x00002000 // Write
#define P_x 0x00001000 // Execute
// Additional operand flags
#define MASK_FLAGS(x) ((x) & 0x00000f00)
#define F_s 0x00000100 // sign-extend 1-byte immediate
#define F_r 0x00000200 // use segment register
#define F_f 0x00000400 // use FPU register
// Mask 0x000000f0 unused atm
// Operand register mask
#define MASK_REG(x) ((x) & 0x0000000f)
// MODRM byte
#define MASK_MODRM_MOD(x) (((x) & 0xc0) >> 6)
#define MASK_MODRM_REG(x) (((x) & 0x38) >> 3)
#define MASK_MODRM_RM(x) ((x) & 0x7)
// SIB byte
#define MASK_SIB_SCALE(x) MASK_MODRM_MOD(x)
#define MASK_SIB_INDEX(x) MASK_MODRM_REG(x)
#define MASK_SIB_BASE(x) MASK_MODRM_RM(x)
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff