Apparently got the mod/rm /r and /[0-7] right for i386

This commit is contained in:
Pierre Pronchery 2011-04-17 04:32:45 +00:00
parent e853ba8c28
commit c48d5cbd39
5 changed files with 73 additions and 41 deletions

View File

@ -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

View File

@ -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

View File

@ -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 */
@ -43,6 +47,11 @@
{ "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 */

View File

@ -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;

View File

@ -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 */