Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
x86_disasm(3)			    libdisasm			   x86_disasm(3)

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

SYNOPSIS
     #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 );

DESCRIPTION
     #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 com-
     pares */
	  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;

EXAMPLES
     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 );

SEE ALSO
     libdisasm(7), x86_format_insn(3), x86_init(3), x86dis(1)

mammon_ 			      0.21			   x86_disasm(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=x86_disasm&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help