GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
x86_disasm(3) libdisasm x86_disasm(3)

x86_disasm, x86_disasm_forward, x86_disasm_range - disassemble a bytestream to x86 assembly language instructions

#include <libdis.h>

typedef void (*DISASM_CALLBACK)( x86_insn_t *, void * );
typedef long (*DISASM_RESOLVER)( x86_op_t *, x86_insn_t *, void * );

int x86_disasm( unsigned char *buf, unsigned int buf_len,
unsigned long buf_rva, unsigned int offset,
x86_insn_t * insn );
int x86_disasm_range( unsigned char *buf, unsigned long buf_rva,
unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg );
int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
unsigned long buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg );

#define MAX_REGNAME 8
#define MAX_PREFIX_STR 32
#define MAX_MNEM_STR 16
#define MAX_INSN_SIZE 20 /* same as in i386.h */
#define MAX_OP_STRING 32 /* max possible operand size in string form */
#define MAX_OP_RAW_STRING 64 /* max possible operand size in raw form */
#define MAX_OP_XML_STRING 256 /* max possible operand size in xml form */
#define MAX_NUM_OPERANDS 8 /* max # implicit and explicit operands */
#define MAX_INSN_STRING 512 /* 2 * 8 * MAX_OP_STRING */
#define MAX_INSN_RAW_STRING 1024 /* 2 * 8 * MAX_OP_RAW_STRING */
#define MAX_INSN_XML_STRING 4096 /* 2 * 8 * MAX_OP_XML_STRING */

enum x86_reg_type { /* NOTE: these may be ORed together */
reg_gen = 0x00001, /* general purpose */
reg_in = 0x00002, /* incoming args, ala RISC */
reg_out = 0x00004, /* args to calls, ala RISC */
reg_local = 0x00008, /* local vars, ala RISC */
reg_fpu = 0x00010, /* FPU data register */
reg_seg = 0x00020, /* segment register */
reg_simd = 0x00040, /* SIMD/MMX reg */
reg_sys = 0x00080, /* restricted/system register */
reg_sp = 0x00100, /* stack pointer */
reg_fp = 0x00200, /* frame pointer */
reg_pc = 0x00400, /* program counter */
reg_retaddr = 0x00800, /* return addr for func */
reg_cond = 0x01000, /* condition code / flags */
reg_zero = 0x02000, /* zero register, ala RISC */
reg_ret = 0x04000, /* return value */
reg_src = 0x10000, /* array/rep source */
reg_dest = 0x20000, /* array/rep destination */
reg_count = 0x40000 /* array/rep/loop counter */
};

typedef struct {
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias of */
unsigned int shift; /* amount to shift aliased reg by */
} x86_reg_t;

typedef struct {
unsigned int scale; /* scale factor */
x86_reg_t index, base; /* index, base registers */
long disp; /* displacement */
char disp_sign; /* is negative? 1/0 */
char disp_size; /* 0, 1, 2, 4 */
} x86_ea_t;

enum x86_op_type { /* mutually exclusive */
op_unused = 0, /* empty/unused operand */
op_register = 1, /* CPU register */
op_immediate = 2, /* Immediate Value */
op_relative_near = 3, /* Relative offset from IP */
op_relative_far = 4,
op_absolute = 5, /* Absolute address (ptr16:32) */
op_expression = 6, /* Address expression (scale/index/base/disp) */
op_offset = 7, /* Offset from start of segment (m32) */
op_unknown
};

enum x86_op_datatype { /* these use Intel's lame terminology */
op_byte = 1, /* 1 byte integer */
op_word = 2, /* 2 byte integer */
op_dword = 3, /* 4 byte integer */
op_qword = 4, /* 8 byte integer */
op_dqword = 5, /* 16 byte integer */
op_sreal = 6, /* 4 byte real (single real) */
op_dreal = 7, /* 8 byte real (double real) */
op_extreal = 8, /* 10 byte real (extended real) */
op_bcd = 9, /* 10 byte binary-coded decimal */
op_simd = 10, /* 16 byte packed (SIMD, MMX) */ op_ssimd = 10, /* 16 byte : 4 packed single FP (SIMD, MMX) */ op_dsimd = 11, /* 16 byte : 2 packed double FP (SIMD, MMX) */ op_sssimd = 12, /* 4 byte : scalar single FP (SIMD, MMX) */ op_sdsimd = 13, /* 8 byte : scalar double FP (SIMD, MMX) */
op_descr32 = 14, /* 6 byte Intel descriptor 2:4 */
op_descr16 = 15, /* 4 byte Intel descriptor 2:2 */
op_pdescr32 = 16, /* 6 byte Intel pseudo-descriptor 32:16 */
op_pdescr16 = 17, /* 6 byte Intel pseudo-descriptor 8:24:16 */
op_fpuenv = 11 /* 28 byte FPU control/environment data */
};

enum x86_op_access { /* ORed together */
op_read = 1,
op_write = 2,
op_execute = 4
};

enum x86_op_flags { /* ORed together, but segs are mutually exclusive */
op_signed = 1, /* signed integer */
op_string = 2, /* possible string or array */
op_constant = 4, /* symbolic constant */
op_pointer = 8, /* operand points to a memory address */
op_sysref = 0x010, /* operand is a syscall number */
op_implied = 0x020, /* operand is implicit in insn */
op_hardcode = 0x040, /* operans is hardcoded in insn */
op_es_seg = 0x100, /* ES segment override */
op_cs_seg = 0x200, /* CS segment override */
op_ss_seg = 0x300, /* SS segment override */
op_ds_seg = 0x400, /* DS segment override */
op_fs_seg = 0x500, /* FS segment override */
op_gs_seg = 0x600 /* GS segment override */
};

typedef struct {
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
enum x86_op_flags flags; /* misc flags */
union {
/* immediate values */
char sbyte;
short sword;
long sdword;
qword sqword;
unsigned char byte;
unsigned short word;
unsigned long dword;
qword qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* absolute address */
void * address;
/* offset from segment */
unsigned long offset;
/* ID of CPU register */
x86_reg_t reg;
/* offsets from current insn */
char relative_near;
long relative_far;
/* effective address [expression] */
x86_ea_t expression;
} data;
void * insn;
} x86_op_t;

typedef struct x86_operand_list {
x86_op_t op;
struct x86_operand_list *next;
} x86_oplist_t;

enum x86_insn_group {
insn_none = 0,
insn_controlflow = 1,
insn_arithmetic = 2,
insn_logic = 3,
insn_stack = 4,
insn_comparison = 5,
insn_move = 6,
insn_string = 7,
insn_bit_manip = 8,
insn_flag_manip = 9,
insn_fpu = 10,
insn_interrupt = 13,
insn_system = 14,
insn_other = 15
};

enum x86_insn_type {
insn_invalid = 0,
/* insn_controlflow */
insn_jmp = 0x1001,
insn_jcc = 0x1002,
insn_call = 0x1003,
insn_callcc = 0x1004,
insn_return = 0x1005,
insn_loop = 0x1006,
/* insn_arithmetic */
insn_add = 0x2001,
insn_sub = 0x2002,
insn_mul = 0x2003,
insn_div = 0x2004,
insn_inc = 0x2005,
insn_dec = 0x2006,
insn_shl = 0x2007,
insn_shr = 0x2008,
insn_rol = 0x2009,
insn_ror = 0x200A,
/* insn_logic */
insn_and = 0x3001,
insn_or = 0x3002,
insn_xor = 0x3003,
insn_not = 0x3004,
insn_neg = 0x3005,
/* insn_stack */
insn_push = 0x4001,
insn_pop = 0x4002,
insn_pushregs = 0x4003,
insn_popregs = 0x4004,
insn_pushflags = 0x4005,
insn_popflags = 0x4006,
insn_enter = 0x4007,
insn_leave = 0x4008,
/* insn_comparison */
insn_test = 0x5001,
insn_cmp = 0x5002,
/* insn_move */
insn_mov = 0x6001, /* move */
insn_movcc = 0x6002, /* conditional move */
insn_xchg = 0x6003, /* exchange */
insn_xchgcc = 0x6004, /* conditional exchange */
/* insn_string */
insn_strcmp = 0x7001,
insn_strload = 0x7002,
insn_strmov = 0x7003,
insn_strstore = 0x7004,
insn_translate = 0x7005, /* xlat */
/* insn_bit_manip */
insn_bittest = 0x8001,
insn_bitset = 0x8002,
insn_bitclear = 0x8003,
/* insn_flag_manip */
insn_clear_carry = 0x9001,
insn_clear_zero = 0x9002,
insn_clear_oflow = 0x9003,
insn_clear_dir = 0x9004,
insn_clear_sign = 0x9005,
insn_clear_parity = 0x9006,
insn_set_carry = 0x9007,
insn_set_zero = 0x9008,
insn_set_oflow = 0x9009,
insn_set_dir = 0x900A,
insn_set_sign = 0x900B,
insn_set_parity = 0x900C,
insn_tog_carry = 0x9010,
insn_tog_zero = 0x9020,
insn_tog_oflow = 0x9030,
insn_tog_dir = 0x9040,
insn_tog_sign = 0x9050,
insn_tog_parity = 0x9060,
/* insn_fpu */
insn_fmov = 0xA001,
insn_fmovcc = 0xA002,
insn_fneg = 0xA003,
insn_fabs = 0xA004,
insn_fadd = 0xA005,
insn_fsub = 0xA006,
insn_fmul = 0xA007,
insn_fdiv = 0xA008,
insn_fsqrt = 0xA009,
insn_fcmp = 0xA00A,
insn_fcos = 0xA00C,
insn_fldpi = 0xA00D,
insn_fldz = 0xA00E,
insn_ftan = 0xA00F,
insn_fsine = 0xA010,
insn_fsys = 0xA020,
/* insn_interrupt */
insn_int = 0xD001,
insn_intcc = 0xD002, /* not present in x86 ISA */
insn_iret = 0xD003,
insn_bound = 0xD004,
insn_debug = 0xD005,
insn_trace = 0xD006,
insn_invalid_op = 0xD007,
insn_oflow = 0xD008,
/* insn_system */
insn_halt = 0xE001,
insn_in = 0xE002, /* input from port/bus */
insn_out = 0xE003, /* output to port/bus */
insn_cpuid = 0xE004,
/* insn_other */
insn_nop = 0xF001,
insn_bcdconv = 0xF002, /* convert to or from BCD */
insn_szconv = 0xF003 /* change size of operand */
};

enum x86_insn_note {
insn_note_ring0 = 1, /* Only available in ring 0 */
insn_note_smm = 2, /* "" in System Management Mode */
insn_note_serial = 4 /* Serializing instruction */
};

enum x86_flag_status {
insn_carry_set = 0x1,
insn_zero_set = 0x2,
insn_oflow_set = 0x4,
insn_dir_set = 0x8,
insn_sign_set = 0x10,
insn_parity_set = 0x20,
insn_carry_or_zero_set = 0x40,
insn_zero_set_or_sign_ne_oflow = 0x80,
insn_carry_clear = 0x100,
insn_zero_clear = 0x200,
insn_oflow_clear = 0x400,
insn_dir_clear = 0x800,
insn_sign_clear = 0x1000,
insn_parity_clear = 0x2000,
insn_sign_eq_oflow = 0x4000,
insn_sign_ne_oflow = 0x8000
};

enum x86_insn_cpu {
cpu_8086 = 1, /* Intel */
cpu_80286 = 2,
cpu_80386 = 3,
cpu_80387 = 4,
cpu_80486 = 5,
cpu_pentium = 6,
cpu_pentiumpro = 7,
cpu_pentium2 = 8,
cpu_pentium3 = 9, >br> cpu_pentium4 = 10,
cpu_k6 = 16, /* AMD */
cpu_k7 = 32,
cpu_athlon = 48
};

enum x86_insn_isa {
isa_gp = 1, /* general purpose */
isa_fp = 2, /* floating point */
isa_fpumgt = 3, /* FPU/SIMD management */
isa_mmx = 4, /* Intel MMX */
isa_sse1 = 5, /* Intel SSE SIMD */
isa_sse2 = 6, /* Intel SSE2 SIMD */
isa_sse3 = 7, /* Intel SSE3 SIMD */
isa_3dnow = 8, /* AMD 3DNow! SIMD */
isa_sys = 9 /* system instructions */
};

enum x86_insn_prefix {
insn_no_prefix = 0,
insn_rep_zero = 1,
insn_rep_notzero = 2,
insn_lock = 4,
insn_delay = 8
};

typedef struct {
/* information about the instruction */
unsigned long addr; /* load address */
unsigned long offset; /* offset into file/buffer */
enum x86_insn_group group; /* meta-type, e.g. INSN_EXEC */
enum x86_insn_type type; /* type, e.g. INSN_BRANCH */
unsigned char bytes[MAX_INSN_SIZE];
unsigned char size; /* size of insn in bytes */
enum x86_insn_prefix prefix;
enum x86_flag_status flags_set; /* flags set or tested by insn */
enum x86_flag_status flags_tested;
/* the instruction proper */
char prefix_string[32]; /* prefixes [might be truncated] */
char mnemonic[8];
x86_op_t operands[3];
/* convenience fields for user */
void *block; /* code block containing this insn */
void *function; /* function containing this insn */
void *tag; /* tag the insn as seen/processed */
} x86_insn_t;
#define X86_WILDCARD_BYTE 0xF4

typedef struct { enum x86_op_type type; /* operand type */ enum x86_op_datatype datatype; /* operand size */ enum x86_op_access access; /* operand access [RWX] */ enum x86_op_flags flags; /* misc flags */
} x86_invariant_op_t;

typedef struct {
unsigned char bytes[64]; /* invariant representation */
unsigned int size; /* number of bytes in insn */ enum x86_insn_group group; /* meta-type, e.g. INSN_EXEC */ enum x86_insn_type type; /* type, e.g. INSN_BRANCH */
x86_invariant_op_t operands[3]; /* use same ordering as x86_insn_t */
} x86_invariant_t;

The following sample callback outputs instructions in raw syntax:

void raw_print( x86_insn_t *insn, void *arg ) { char line[1024]; x86_format_insn(insn, line, 1024, raw_syntax); printf( "%s0, line);
}

The following sample resolver performs very limited checking on the operand of a jump or call to determine what program address the operand refers to:

long resolver( x86_op_t *op, x86_insn_t *insn ) { long retval = -1; /* this is a flat ripoff of internal_resolver in libdis.c -- we don't do any register or stack resolving, or check to see if we have already encountered this RVA */ if ( op->type == op_absolute || op->type == op_offset ) { retval = op->data.sdword; } else if (op->type == op_relative ){ if ( op->datatype == op_byte ) { retval = insn->addr + insn->size + op->data.sbyte; } else if ( op->datatype == op_word ) { retval = insn->addr + insn->size + op->data.sword; } else if ( op->datatype == op_dword ) { retval = insn->addr + insn->size + op->data.sdword; } } return( retval );
}

The following code snippets demonstrate how to use the various disassembly routines:

unsigned char *buf; /* buffer of bytes to disassemble */ unsigned int buf_len;/* length of buffer */ unsigned long rva; /* load address of start of buffer */ unsigned int pos; /* position in buffer */ x86_insn_t insn; /* disassembled instruction */

/* disassemble entire buffer, printing automatically */ x86_disasm_range( buf, buf_rva, pos, buf_len, raw_print, NULL );

/* disassemble a single instruction, then print it */ if (x86_disasm( buf, buf_len, buf_rva, pos, &insn ) ) { raw_print( &insn, NULL ); }

/* disassemble forward in 'buf' starting at 'pos' */ x86_disasm_forward( buf, buf_len, buf_rva, pos, raw_print, NULL, resolver );

libdisasm(7), x86_format_insn(3), x86_init(3), x86dis(1)
0.21 mammon_

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.