diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c index 87166713..d11b868e 100644 --- a/arch/X86/X86IntelInstPrinter.c +++ b/arch/X86/X86IntelInstPrinter.c @@ -267,6 +267,86 @@ static void printRegName(SStream *OS, unsigned RegNo) SStream_concat0(OS, getRegisterName(RegNo)); } +// for MASM syntax, 0x123 = 123h, 0xA123 = 0A123h +// this function tell us if we need to have prefix 0 in front of a number +static bool need_zero_prefix(uint64_t imm) +{ + // find the first hex letter representing imm + while(imm > 0x10) + imm >>= 4; + + if (imm < 0xa) + return false; + else // this need 0 prefix + return true; +} + +static void printImm(int syntax, SStream *O, int64_t imm, bool positive) +{ + if (positive) { + // always print this number in positive form + if (syntax == CS_OPT_SYNTAX_MASM) { + if (imm < 0) { + if (need_zero_prefix(imm)) + SStream_concat(O, "0%"PRIx64"h", imm); + else + SStream_concat(O, "%"PRIx64"h", imm); + } else { + if (imm > HEX_THRESHOLD) { + if (need_zero_prefix(imm)) + SStream_concat(O, "0%"PRIx64"h", imm); + else + SStream_concat(O, "%"PRIx64"h", imm); + } else + SStream_concat(O, "%"PRIu64, imm); + } + } else { // Intel syntax + if (imm < 0) { + SStream_concat(O, "0x%"PRIx64, imm); + } else { + if (imm > HEX_THRESHOLD) + SStream_concat(O, "0x%"PRIx64, imm); + else + SStream_concat(O, "%"PRIu64, imm); + } + } + } else { + if (syntax == CS_OPT_SYNTAX_MASM) { + if (imm < 0) { + if (imm < -HEX_THRESHOLD) { + if (need_zero_prefix(imm)) + SStream_concat(O, "-0%"PRIx64"h", -imm); + else + SStream_concat(O, "-%"PRIx64"h", -imm); + } else + SStream_concat(O, "-%"PRIu64, -imm); + + } else { + if (imm > HEX_THRESHOLD) { + if (need_zero_prefix(imm)) + SStream_concat(O, "0%"PRIx64"h", imm); + else + SStream_concat(O, "%"PRIx64"h", imm); + } else + SStream_concat(O, "%"PRIu64, imm); + } + } else { // Intel syntax + if (imm < 0) { + if (imm < -HEX_THRESHOLD) + SStream_concat(O, "-0x%"PRIx64, -imm); + else + SStream_concat(O, "-%"PRIu64, -imm); + + } else { + if (imm > HEX_THRESHOLD) + SStream_concat(O, "0x%"PRIx64, imm); + else + SStream_concat(O, "%"PRIu64, imm); + } + } + } +} + // local printOperand, without updating public operands static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) { @@ -275,18 +355,7 @@ static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) printRegName(O, MCOperand_getReg(Op)); } else if (MCOperand_isImm(Op)) { int64_t imm = MCOperand_getImm(Op); - if (imm < 0) { - if (imm < -HEX_THRESHOLD) - SStream_concat(O, "-0x%"PRIx64, -imm); - else - SStream_concat(O, "-%"PRIu64, -imm); - - } else { - if (imm > HEX_THRESHOLD) - SStream_concat(O, "0x%"PRIx64, imm); - else - SStream_concat(O, "%"PRIu64, imm); - } + printImm(MI->csh->syntax, O, imm, false); } } @@ -488,14 +557,11 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O) int64_t imm = MCOperand_getImm(DispSpec); if (MI->csh->detail) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm; - if (imm < 0) { - SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm); - } else { - if (imm > HEX_THRESHOLD) - SStream_concat(O, "0x%"PRIx64, imm); - else - SStream_concat(O, "%"PRIu64, imm); - } + + if (imm < 0) + printImm(MI->csh->syntax, O, arch_masks[MI->csh->mode] & imm, true); + else + printImm(MI->csh->syntax, O, imm, true); } SStream_concat0(O, "]"); @@ -512,10 +578,7 @@ static void printU8Imm(MCInst *MI, unsigned Op, SStream *O) { uint8_t val = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xff; - if (val > HEX_THRESHOLD) - SStream_concat(O, "0x%x", val); - else - SStream_concat(O, "%u", val); + printImm(MI->csh->syntax, O, val, true); if (MI->csh->detail) { #ifndef CAPSTONE_DIET @@ -631,18 +694,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O) imm = imm & 0xffffffff; } - if (imm < 0) { - SStream_concat(O, "0x%"PRIx64, imm); - } else { - // handle 16bit segment bound - if (MI->csh->mode == CS_MODE_16) - imm = imm & 0xffff; + if (MI->csh->mode == CS_MODE_16) + imm = imm & 0xffff; + + printImm(MI->csh->syntax, O, imm, true); - if (imm > HEX_THRESHOLD) - SStream_concat(O, "0x%"PRIx64, imm); - else - SStream_concat(O, "%"PRIu64, imm); - } if (MI->csh->detail) { #ifndef CAPSTONE_DIET uint8_t access[6]; @@ -708,27 +764,13 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) switch(MI->flat_insn->id) { default: - if (imm >= 0) { - if (imm > HEX_THRESHOLD) - SStream_concat(O, "0x%"PRIx64, imm); - else - SStream_concat(O, "%"PRIu64, imm); - } else { - if (imm < -HEX_THRESHOLD) - SStream_concat(O, "-0x%"PRIx64, -imm); - else - SStream_concat(O, "-%"PRIu64, -imm); - } - + printImm(MI->csh->syntax, O, imm, false); break; case X86_INS_INT: // do not print number in negative form imm = imm & 0xff; - if (imm >= 0 && imm <= HEX_THRESHOLD) - SStream_concat(O, "%u", imm); - else - SStream_concat(O, "0x%x", imm); + printImm(MI->csh->syntax, O, imm, true); break; case X86_INS_AND: @@ -736,20 +778,20 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) case X86_INS_XOR: // do not print number in negative form if (imm >= 0 && imm <= HEX_THRESHOLD) - SStream_concat(O, "%u", imm); + printImm(MI->csh->syntax, O, imm, true); else { imm = arch_masks[opsize? opsize : MI->imm_size] & imm; - SStream_concat(O, "0x%"PRIx64, imm); + printImm(MI->csh->syntax, O, imm, true); } break; case X86_INS_RET: // RET imm16 if (imm >= 0 && imm <= HEX_THRESHOLD) - SStream_concat(O, "%u", imm); + printImm(MI->csh->syntax, O, imm, true); else { imm = 0xffff & imm; - SStream_concat(O, "0x%x", 0xffff & imm); + printImm(MI->csh->syntax, O, imm, true); } break; } @@ -843,25 +885,18 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O) if (DispVal) { if (NeedPlus) { if (DispVal < 0) { - if (DispVal < -HEX_THRESHOLD) - SStream_concat(O, " - 0x%"PRIx64, -DispVal); - else - SStream_concat(O, " - %"PRIu64, -DispVal); + SStream_concat0(O, " - "); + printImm(MI->csh->syntax, O, -DispVal, true); } else { - if (DispVal > HEX_THRESHOLD) - SStream_concat(O, " + 0x%"PRIx64, DispVal); - else - SStream_concat(O, " + %"PRIu64, DispVal); + SStream_concat0(O, " + "); + printImm(MI->csh->syntax, O, DispVal, true); } } else { // memory reference to an immediate address if (DispVal < 0) { - SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal); + printImm(MI->csh->syntax, O, arch_masks[MI->csh->mode] & DispVal, true); } else { - if (DispVal > HEX_THRESHOLD) - SStream_concat(O, "0x%"PRIx64, DispVal); - else - SStream_concat(O, "%"PRIu64, DispVal); + printImm(MI->csh->syntax, O, DispVal, true); } } diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index ac863413..185a4e92 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -3055,7 +3055,7 @@ void op_addImm(MCInst *MI, int v) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM; MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = v; // if op_count > 0, then this operand's size is taken from the destination op - if (MI->csh->syntax == CS_OPT_SYNTAX_INTEL) { + if (MI->csh->syntax != CS_OPT_SYNTAX_ATT) { if (MI->flat_insn->detail->x86.op_count > 0) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size; else diff --git a/arch/X86/X86Module.c b/arch/X86/X86Module.c index 5c3803d0..25910771 100644 --- a/arch/X86/X86Module.c +++ b/arch/X86/X86Module.c @@ -65,8 +65,13 @@ static cs_err option(cs_struct *handle, cs_opt_type type, size_t value) case CS_OPT_SYNTAX_DEFAULT: case CS_OPT_SYNTAX_INTEL: - handle->printer = X86_Intel_printInst; handle->syntax = CS_OPT_SYNTAX_INTEL; + handle->printer = X86_Intel_printInst; + break; + + case CS_OPT_SYNTAX_MASM: + handle->printer = X86_Intel_printInst; + handle->syntax = value; break; case CS_OPT_SYNTAX_ATT: diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index db4c893e..b49e03f2 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -154,6 +154,7 @@ typedef enum cs_opt_value { CS_OPT_SYNTAX_INTEL, // X86 Intel asm syntax - default on X86 (CS_OPT_SYNTAX). CS_OPT_SYNTAX_ATT, // X86 ATT asm syntax (CS_OPT_SYNTAX). CS_OPT_SYNTAX_NOREGNAME, // Prints register name with only number (CS_OPT_SYNTAX) + CS_OPT_SYNTAX_MASM, // X86 Intel Masm syntax (CS_OPT_SYNTAX). } cs_opt_value; //> Common instruction operand types - to be consistent across all architectures. diff --git a/tests/test_basic.c b/tests/test_basic.c index 371ba37d..c2e2bcab 100644 --- a/tests/test_basic.c +++ b/tests/test_basic.c @@ -32,7 +32,7 @@ static void test() { #ifdef CAPSTONE_HAS_X86 #define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" -#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" +#define X86_CODE32 "\xba\xcd\xab\x00\x00\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" //#define X86_CODE32 "\x0f\xa7\xc0" // xstorerng #define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00" #endif @@ -106,6 +106,15 @@ static void test() sizeof(X86_CODE32) - 1, "X86 32 (Intel syntax)" }, + { + CS_ARCH_X86, + CS_MODE_32, + (unsigned char*)X86_CODE32, + sizeof(X86_CODE32) - 1, + "X86 32 (MASM syntax)", + CS_OPT_SYNTAX, + CS_OPT_SYNTAX_MASM, + }, { CS_ARCH_X86, CS_MODE_64,