diff --git a/src/arch.c b/src/arch.c index d1ead4a..ff4ab54 100644 --- a/src/arch.c +++ b/src/arch.c @@ -282,6 +282,10 @@ static int _call_operands_immediate(ArchOperandDefinition definition, value >>= size; if(value > 0) return -1; + /* check if it is signed */ + if(operand->value.immediate.negative + && !(AO_GET_FLAGS(definition) & AOF_SIGNED)) + return -1; return 0; } diff --git a/src/arch/i386.c b/src/arch/i386.c index f5a6084..edbeaae 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -175,19 +175,20 @@ static int _write_dregister(ArchPlugin * plugin, uint32_t * i, static int _write_immediate(ArchPlugin * plugin, ArchOperandDefinition definition, ArchOperand * operand) { + uint64_t value = operand->value.immediate.value; + + if(AO_GET_FLAGS(definition) & AOF_SIGNED) + value = -value; switch(AO_GET_SIZE(definition) >> 3) { case 0: return 0; case sizeof(uint8_t): - return _write_immediate8(plugin, - operand->value.immediate.value); + return _write_immediate8(plugin, value); case sizeof(uint16_t): - return _write_immediate16(plugin, - operand->value.immediate.value); + return _write_immediate16(plugin, value); case sizeof(uint32_t): - return _write_immediate32(plugin, - operand->value.immediate.value); + return _write_immediate32(plugin, value); default: return -1; } diff --git a/src/arch/i386.ins b/src/arch/i386.ins index 73dba06..f76bfd0 100644 --- a/src/arch/i386.ins +++ b/src/arch/i386.ins @@ -36,6 +36,8 @@ #define OP_RMW_RW AO_REGISTER(AOF_I386_MODRM, W, 0) /* 0xc0 */ /* immediate values */ +#define OP_S8 AO_IMMEDIATE(AOF_SIGNED, 0, 8) +#define OP_SW AO_IMMEDIATE(AOF_SIGNED, 0, W) #define OP_U8 AO_IMMEDIATE(0, 0, 8) #define OP_UW AO_IMMEDIATE(0, 0, W) @@ -60,19 +62,24 @@ { "adc", 0x12, OP1F, OP_RM8_R8_R,OP_RM8_R8_R,AOT_NONE }, #endif /* ADC 0x14 ib 1 al imm8 */ -{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE }, +{ "adc", 0x14, OP1F, OP_al, OP_S8, AOT_NONE }, /* ADC 0x15 iW 1 AX immW */ -{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE }, +{ "adc", 0x15, OP1F, OP_AX, OP_SW, 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", 0x80, OP1F, OP_RM8_D0+2,OP_S8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_D8+2,OP_S8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_DW+2,OP_S8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_R8+2,OP_S8, 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 }, +{ "adc", 0x81, OP1F, OP_RMW_D0+2,OP_SW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_D8+2,OP_SW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_DW+2,OP_SW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_RW+2,OP_SW, AOT_NONE }, +/* ADC 0x83 /2 i8 1 r/m8 imm8 */ +{ "adc", 0x83, OP1F, OP_RMW_D0+2,OP_S8, AOT_NONE }, +{ "adc", 0x83, OP1F, OP_RMW_D8+2,OP_S8, AOT_NONE }, +{ "adc", 0x83, OP1F, OP_RMW_DW+2,OP_S8, AOT_NONE }, +{ "adc", 0x83, OP1F, OP_RMW_RW+2,OP_S8, AOT_NONE }, /* ADD 0x04 ib 1 al imm8 */ { "add", 0x04, OP1F, OP_al, OP_U8, AOT_NONE }, /* ADD 0x05 iW 1 AX immW */ @@ -82,7 +89,7 @@ { "add", 0x80, OP1F, OP_RM8_D8+0,OP_U8, AOT_NONE }, { "add", 0x80, OP1F, OP_RM8_DW+0,OP_U8, AOT_NONE }, { "add", 0x80, OP1F, OP_RM8_R8+0,OP_U8, AOT_NONE }, -/* ADC 0x81 /0 iW 1 r/m8 imm8 */ +/* ADD 0x81 /0 iW 1 r/m8 imm8 */ { "add", 0x81, OP1F, OP_RMW_D0+0,OP_UW, AOT_NONE }, { "add", 0x81, OP1F, OP_RMW_D8+0,OP_UW, AOT_NONE }, { "add", 0x81, OP1F, OP_RMW_DW+0,OP_UW, AOT_NONE }, diff --git a/test/i386.S b/test/i386.S index 2a90751..6aca98d 100644 --- a/test/i386.S +++ b/test/i386.S @@ -26,6 +26,7 @@ /* 81 93 19 18 17 16 4b */ /* 4a 49 48 */ adc %ecx, $0x45464748 /* 81 d1 45 46 47 48 */ + adc [%eax], -$0x02 /* 83 10 fe */ /* ADD */ add %al, $0x40 /* 04 40 */ add %eax, $0x41424344 /* 05 44 43 42 41 */