From e853ba8c28b95d52656f2ba9f7fa29a6693f56d5 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sun, 17 Apr 2011 04:02:20 +0000 Subject: [PATCH] Beginning to get the Mod R/M byte right (not considering the SIB at all) --- include/Asm/arch.h | 5 ++-- src/arch/i386.c | 52 ++++++++++++++++++++++++++++++++++------ src/arch/i386.ins | 59 +++++++++++++++++++++++++++++----------------- test/i386.S | 21 +++++++++++------ 4 files changed, 98 insertions(+), 39 deletions(-) diff --git a/include/Asm/arch.h b/include/Asm/arch.h index fcbf617..a31ee00 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -67,11 +67,10 @@ typedef enum _ArchOperandType # define AOM_VALUE 0x000000ff /* flags */ -# define AOF_FILTER 0x1 /* for immediate */ -# define AOF_SIGNED 0x2 +# define AOF_SIGNED 0x1 /* for registers */ -# define AOF_IMPLICIT 0x2 +# define AOF_IMPLICIT 0x1 /* macros */ # define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS) diff --git a/src/arch/i386.c b/src/arch/i386.c index 8cb3841..31f6620 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -118,17 +118,51 @@ static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, static int _write_dregister(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand) { - /* FIXME really implement */ - return _write_register(plugin, definition, operand); + ArchPluginHelper * helper = plugin->helper; + char const * name = operand->value._register.name; + size_t size = AO_GET_SIZE(definition); + ArchRegister * ar; + ArchOperandDefinition idefinition; + ArchOperand ioperand; + + if((ar = helper->get_register_by_name_size(helper->arch, name, size)) + == NULL) + return -1; + /* write register */ + idefinition = AO_IMMEDIATE(0, 0, 8); + memset(&ioperand, 0, sizeof(ioperand)); + ioperand.type = AOT_IMMEDIATE; + ioperand.value.immediate.value = ar->id; + if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) + ioperand.value.immediate.value |= (AO_GET_VALUE(definition) + << 3); + if(operand->value.dregister.offset == 0) + /* there is no offset */ + return _write_immediate(plugin, idefinition, &ioperand); + /* declare offset */ + switch(AO_GET_OFFSET(definition) >> 3) + { + case sizeof(uint8_t): + ioperand.value.immediate.value |= 0x40; + break; + case W >> 3: + ioperand.value.immediate.value |= 0x80; + break; + default: + return -1; /* FIXME report error */ + } + if(_write_immediate(plugin, idefinition, &ioperand) != 0) + return -1; + /* write offset */ + idefinition = AO_IMMEDIATE(0, 0, AO_GET_OFFSET(definition)); + ioperand.value.immediate.value = operand->value.dregister.offset; + return _write_immediate(plugin, idefinition, &ioperand); } static int _write_immediate(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand) { - size_t size; - - size = AO_GET_SIZE(definition) >> 3; - switch(size) + switch(AO_GET_SIZE(definition) >> 3) { case 0: return 0; @@ -231,6 +265,10 @@ static int _write_register(ArchPlugin * plugin, idefinition = AO_IMMEDIATE(0, 0, 8); memset(&ioperand, 0, sizeof(ioperand)); ioperand.type = AOT_IMMEDIATE; - ioperand.value.immediate.value = ar->id; + if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) + ioperand.value.immediate.value = 0xc0 | ar->id + | (AO_GET_VALUE(definition) << 3); + else + ioperand.value.immediate.value = ar->id; return _write_immediate(plugin, idefinition, &ioperand); } diff --git a/src/arch/i386.ins b/src/arch/i386.ins index b803a75..4b2820d 100644 --- a/src/arch/i386.ins +++ b/src/arch/i386.ins @@ -7,40 +7,55 @@ # define REG_AX_id REG_eax_id #endif + +/* helpers */ +/* opcodes */ +#define OP1F (8 << AOD_SIZE) +#define OP2F (16 << AOD_SIZE) + +/* operands */ /* registers */ +#define OP_R8 AO_REGISTER(0, 8, 0) +#define OP_RW AO_REGISTER(0, W, 0) #define OP_al AO_REGISTER(AOF_IMPLICIT, REG_al_size, REG_al_id) #define OP_AX AO_REGISTER(AOF_IMPLICIT, W, REG_AX_id) -/* helpers */ -#define OP1F (8 << AOD_SIZE) -#define OP2F (16 << AOD_SIZE) /* mod r/m byte */ -#define OP_RM8_D0 AO_DREGISTER(0, 0, 8, 0) -#define OP_RM8_D8 AO_DREGISTER(0, 8, 8, 0) -#define OP_RM8_DW AO_DREGISTER(0, W, 8, 0) -#define OP_RM8_RW AO_REGISTER(0, 8, 0) -#define OP_RMW_D0 AO_DREGISTER(0, 0, W, 0) -#define OP_RMW_D8 AO_DREGISTER(0, 8, W, 0) -#define OP_RMW_DW AO_DREGISTER(0, W, W, 0) -#define OP_RMW_RW AO_REGISTER(0, W, 0) +#define AOF_I386_MODRM 0x2 +#define OP_RM8_D0 AO_DREGISTER(AOF_I386_MODRM, 0, W, 0) /* 0x00 */ +#define OP_RM8_D8 AO_DREGISTER(AOF_I386_MODRM, 8, W, 0) /* 0x40 */ +#define OP_RM8_DW AO_DREGISTER(AOF_I386_MODRM, W, W, 0) /* 0x80 */ +#define OP_RM8_R8 AO_REGISTER(AOF_I386_MODRM, 8, 0) /* 0xc0 */ +#define OP_RMW_D0 AO_DREGISTER(AOF_I386_MODRM, 0, W, 0) /* 0x00 */ +#define OP_RMW_D8 AO_DREGISTER(AOF_I386_MODRM, 8, W, 0) /* 0x40 */ +#define OP_RMW_DW AO_DREGISTER(AOF_I386_MODRM, W, W, 0) /* 0x80 */ +#define OP_RMW_RW AO_REGISTER(AOF_I386_MODRM, W, 0) /* 0xc0 */ + /* immediate values */ #define OP_U8 AO_IMMEDIATE(0, 0, 8) #define OP_UW AO_IMMEDIATE(0, 0, W) + +/* instructions */ { "aaa", 0x37, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aad", 0xd50a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aad", 0xd5, OP1F, OP_U8, AOT_NONE, AOT_NONE }, { "aam", 0xd40a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aam", 0xd4, OP1F, OP_U8, AOT_NONE, AOT_NONE }, { "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, -{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE }, -{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE }, -{ "adc", 0x80, OP1F, OP_RM8_D0,OP_U8, AOT_NONE }, -{ "adc", 0x80, OP1F, OP_RM8_D8,OP_U8, AOT_NONE }, -{ "adc", 0x80, OP1F, OP_RM8_DW,OP_U8, AOT_NONE }, -{ "adc", 0x80, OP1F, OP_RM8_RW,OP_U8, AOT_NONE }, -{ "adc", 0x81, OP1F, OP_RMW_D0,OP_UW, AOT_NONE }, -{ "adc", 0x81, OP1F, OP_RMW_D8,OP_UW, AOT_NONE }, -{ "adc", 0x81, OP1F, OP_RMW_DW,OP_UW, AOT_NONE }, -{ "adc", 0x81, OP1F, OP_RMW_RW,OP_UW, AOT_NONE }, -{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, +/* ADC 0x14 ib 1 al imm8 */ +{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE }, +/* ADC 0x15 iW 1 AX immW */ +{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE }, +/* ADC 0x80 /2 ib 1 r/m8 imm8 */ +{ "adc", 0x80, OP1F, OP_RM8_D0+2,OP_U8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_D8+2,OP_U8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_DW+2,OP_U8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_R8+2,OP_U8, AOT_NONE }, +/* ADC 0x81 /2 iW 1 r/m8 imm8 */ +{ "adc", 0x81, OP1F, OP_RMW_D0+2,OP_UW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_D8+2,OP_UW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_DW+2,OP_UW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_RW+2,OP_UW, AOT_NONE }, +/* NOP */ +{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, diff --git a/test/i386.S b/test/i386.S index 2bc611a..a961b30 100644 --- a/test/i386.S +++ b/test/i386.S @@ -1,3 +1,4 @@ +/* $Id$ */ .text aaa aad @@ -5,11 +6,17 @@ aam aam $0x42 aas - adc %al, $0x42 - adc %eax, $0x42 - adc [%edx], $0x42 - adc [%ebx + $0x5], $0x42 - adc %ecx, $0x42 - adc [%edx], $0x42434445 - adc %ebx, $0x42434445 + /* ADC */ + adc %al, $0x40 /* 14 40 */ + adc %eax, $0x41424344 /* 15 41 42 43 44 */ + adc [%edx], $0x46 /* 80 12 46 */ + adc [%ebx + $0x15], $0x47 /* 80 53 15 47 */ + adc [%ebx + $0x16171819], $0x48 /* 80 93 19 18 17 16 48 */ + adc %cl, $0x45 /* 80 d1 45 */ + adc [%edx], $0x46474849 /* 81 12 46 47 48 49 */ + adc [%ebx + $0x14], $0x4748494a /* 81 53 14 47 48 49 4a */ + adc [%ebx + $0x16171819], $0x48494a4b + /* 81 93 19 18 17 16 4b */ + /* 4a 49 48 */ + adc %ecx, $0x45464748 /* 81 d1 45 46 47 48 */ nop