From c48d5cbd39808a9eea36d095ecc7b145cf26960c Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Sun, 17 Apr 2011 04:32:45 +0000 Subject: [PATCH] Apparently got the mod/rm /r and /[0-7] right for i386 --- include/Asm/arch.h | 2 +- src/arch/i386.c | 80 +++++++++++++++++++++++++++++++--------------- src/arch/i386.ins | 21 ++++++++---- src/parser.c | 9 ------ test/i386.S | 2 ++ 5 files changed, 73 insertions(+), 41 deletions(-) diff --git a/include/Asm/arch.h b/include/Asm/arch.h index a31ee00..f9ea295 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -155,7 +155,7 @@ typedef struct _ArchInstructionCall { char const * name; ArchOperand operands[3]; - size_t operands_cnt; + uint32_t operands_cnt; } ArchInstructionCall; typedef struct _ArchRegister diff --git a/src/arch/i386.c b/src/arch/i386.c index 31f6620..0eaaecd 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -81,44 +81,45 @@ ArchPlugin arch_plugin = /* functions */ -static int _write_dregister(ArchPlugin * plugin, - ArchOperandDefinition definition, ArchOperand * operand); +static int _write_dregister(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands); static int _write_immediate(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand); static int _write_immediate8(ArchPlugin * plugin, uint8_t value); static int _write_immediate16(ArchPlugin * plugin, uint16_t value); static int _write_immediate32(ArchPlugin * plugin, uint32_t value); static int _write_opcode(ArchPlugin * plugin, ArchInstruction * instruction); -static int _write_operand(ArchPlugin * plugin, ArchOperandDefinition definition, - ArchOperand * operand); -static int _write_register(ArchPlugin * plugin, - ArchOperandDefinition definition, ArchOperand * operand); +static int _write_operand(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands); +static int _write_register(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands); static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, ArchInstructionCall * call) { - size_t i; - ArchOperandDefinition definition; + uint32_t i; + ArchOperandDefinition definitions[3]; #ifdef DEBUG fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); #endif if(_write_opcode(plugin, instruction) != 0) return -1; + definitions[0] = instruction->op1; + definitions[1] = instruction->op2; + definitions[2] = instruction->op3; for(i = 0; i < call->operands_cnt; i++) - { - definition = (i == 0) ? instruction->op1 : ((i == 1) - ? instruction->op2 : instruction->op3); - if(_write_operand(plugin, definition, &call->operands[i]) != 0) + if(_write_operand(plugin, &i, definitions, call->operands) != 0) return -1; - } return 0; } -static int _write_dregister(ArchPlugin * plugin, - ArchOperandDefinition definition, ArchOperand * operand) +static int _write_dregister(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands) { ArchPluginHelper * helper = plugin->helper; + ArchOperandDefinition definition = definitions[*i]; + ArchOperand * operand = &operands[*i]; char const * name = operand->value._register.name; size_t size = AO_GET_SIZE(definition); ArchRegister * ar; @@ -133,7 +134,18 @@ static int _write_dregister(ArchPlugin * plugin, memset(&ioperand, 0, sizeof(ioperand)); ioperand.type = AOT_IMMEDIATE; ioperand.value.immediate.value = ar->id; - if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) + if(AO_GET_FLAGS(definition) & AOF_I386_MODRM + && AO_GET_VALUE(definition) == 8) /* mod r/m, /r */ + { + (*i)++; /* skip next operand */ + name = operands[*i].value._register.name; + size = AO_GET_SIZE(definitions[*i]); + if((ar = helper->get_register_by_name_size(helper->arch, name, + size)) == NULL) + return -1; + ioperand.value.immediate.value |= (ar->id << 3); + } + else if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) /* mod r/m, /[0-7] */ ioperand.value.immediate.value |= (AO_GET_VALUE(definition) << 3); if(operand->value.dregister.offset == 0) @@ -232,25 +244,30 @@ static int _write_opcode(ArchPlugin * plugin, ArchInstruction * instruction) return _write_immediate(plugin, instruction->flags, &operand); } -static int _write_operand(ArchPlugin * plugin, ArchOperandDefinition definition, - ArchOperand * operand) +static int _write_operand(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands) { - switch(operand->type) + switch(operands[*i].type) { case AOT_DREGISTER: - return _write_dregister(plugin, definition, operand); + return _write_dregister(plugin, i, definitions, + operands); case AOT_IMMEDIATE: - return _write_immediate(plugin, definition, operand); + return _write_immediate(plugin, definitions[*i], + &operands[*i]); case AOT_REGISTER: - return _write_register(plugin, definition, operand); + return _write_register(plugin, i, definitions, + operands); } return 0; } -static int _write_register(ArchPlugin * plugin, - ArchOperandDefinition definition, ArchOperand * operand) +static int _write_register(ArchPlugin * plugin, uint32_t * i, + ArchOperandDefinition * definitions, ArchOperand * operands) { ArchPluginHelper * helper = plugin->helper; + ArchOperandDefinition definition = definitions[*i]; + ArchOperand * operand = &operands[*i]; char const * name = operand->value._register.name; size_t size = AO_GET_SIZE(definition); ArchRegister * ar; @@ -262,10 +279,23 @@ static int _write_register(ArchPlugin * plugin, 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; - if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) + ioperand.value.immediate.value = ar->id; + if(AO_GET_FLAGS(definition) & AOF_I386_MODRM + && AO_GET_VALUE(definition) == 8) /* mod r/m, /r */ + { + (*i)++; /* skip next operand */ + name = operands[*i].value._register.name; + size = AO_GET_SIZE(definitions[*i]); + if((ar = helper->get_register_by_name_size(helper->arch, name, + size)) == NULL) + return -1; + ioperand.value.immediate.value |= 0xc0 | (ar->id << 3); + } + else if(AO_GET_FLAGS(definition) & AOF_I386_MODRM) /* mod r/m, /[0-7] */ ioperand.value.immediate.value = 0xc0 | ar->id | (AO_GET_VALUE(definition) << 3); else diff --git a/src/arch/i386.ins b/src/arch/i386.ins index 4b2820d..4e04674 100644 --- a/src/arch/i386.ins +++ b/src/arch/i386.ins @@ -26,6 +26,10 @@ #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_RM8_D0_R AO_DREGISTER(AOF_I386_MODRM, 0, W, 8) /* 0x00 */ +#define OP_RM8_D8_R AO_DREGISTER(AOF_I386_MODRM, 8, W, 8) /* 0x40 */ +#define OP_RM8_DW_R AO_DREGISTER(AOF_I386_MODRM, W, W, 8) /* 0x80 */ +#define OP_RM8_R8_R AO_REGISTER(AOF_I386_MODRM, 8, 8) /* 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 */ @@ -37,12 +41,17 @@ /* 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 }, +{ "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 0x10 /r 1 r/m8 r8 */ +{ "adc", 0x10, OP1F, OP_RM8_D0_R,OP_R8, AOT_NONE }, +{ "adc", 0x10, OP1F, OP_RM8_D8_R,OP_R8, AOT_NONE }, +{ "adc", 0x10, OP1F, OP_RM8_DW_R,OP_R8, AOT_NONE }, +{ "adc", 0x10, OP1F, OP_RM8_R8_R,OP_R8, AOT_NONE }, /* ADC 0x14 ib 1 al imm8 */ { "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE }, /* ADC 0x15 iW 1 AX immW */ diff --git a/src/parser.c b/src/parser.c index 6b163fa..c85d82f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -35,15 +35,6 @@ typedef struct _State unsigned int warning_cnt; Code * code; ArchInstructionCall call; -#if 0 - char const * name; - struct - { - ArchOperandDefinition definition; - ArchOperand operand; - } operands[3]; - size_t operands_cnt; -#endif } State; diff --git a/test/i386.S b/test/i386.S index a961b30..bc838dc 100644 --- a/test/i386.S +++ b/test/i386.S @@ -7,6 +7,8 @@ aam $0x42 aas /* ADC */ + adc [%ecx], %dh /* 10 31 */ + adc %bl, %bh /* 10 fb */ adc %al, $0x40 /* 14 40 */ adc %eax, $0x41424344 /* 15 41 42 43 44 */ adc [%edx], $0x46 /* 80 12 46 */