📄 disasm-ia32.cc.svn-base
字号:
AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp); return mod == 2 ? 5 : 2; } break; case 3: AppendToBuffer("%s", NameOfCPURegister(rm)); return 1; default: UnimplementedInstruction(); return 1; } UNREACHABLE();}// Returns number of bytes used including the current *data.// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.int DisassemblerIA32::PrintOperands(const char* mnem, OperandOrder op_order, byte* data) { byte modrm = *data; int mod, regop, rm; get_modrm(modrm, &mod, ®op, &rm); int advance = 0; switch (op_order) { case REG_OPER_OP_ORDER: { AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); advance = PrintRightOperand(data); break; } case OPER_REG_OP_ORDER: { AppendToBuffer("%s ", mnem); advance = PrintRightOperand(data); AppendToBuffer(",%s", NameOfCPURegister(regop)); break; } default: UNREACHABLE(); break; } return advance;}// Returns number of bytes used by machine instruction, including *data byte.// Writes immediate instructions to 'tmp_buffer_'.int DisassemblerIA32::PrintImmediateOp(byte* data) { bool sign_extension_bit = (*data & 0x02) != 0; byte modrm = *(data+1); int mod, regop, rm; get_modrm(modrm, &mod, ®op, &rm); const char* mnem = "Imm???"; switch (regop) { case 0: mnem = "add"; break; case 1: mnem = "or"; break; case 2: mnem = "adc"; break; case 4: mnem = "and"; break; case 5: mnem = "sub"; break; case 6: mnem = "xor"; break; case 7: mnem = "cmp"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s ", mnem); int count = PrintRightOperand(data+1); if (sign_extension_bit) { AppendToBuffer(",0x%x", *(data + 1 + count)); return 1 + count + 1 /*int8*/; } else { AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); return 1 + count + 4 /*int32_t*/; }}// Returns number of bytes used, including *data.int DisassemblerIA32::F7Instruction(byte* data) { assert(*data == 0xF7); byte modrm = *(data+1); int mod, regop, rm; get_modrm(modrm, &mod, ®op, &rm); if (mod == 3 && regop != 0) { const char* mnem = NULL; switch (regop) { case 2: mnem = "not"; break; case 3: mnem = "neg"; break; case 4: mnem = "mul"; break; case 7: mnem = "idiv"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm)); return 2; } else if (mod == 3 && regop == eax) { int32_t imm = *reinterpret_cast<int32_t*>(data+2); AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm); return 6; } else if (regop == eax) { AppendToBuffer("test "); int count = PrintRightOperand(data+1); int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); AppendToBuffer(",0x%x", imm); return 1+count+4 /*int32_t*/; } else { UnimplementedInstruction(); return 2; }}int DisassemblerIA32::D1D3C1Instruction(byte* data) { byte op = *data; assert(op == 0xD1 || op == 0xD3 || op == 0xC1); byte modrm = *(data+1); int mod, regop, rm; get_modrm(modrm, &mod, ®op, &rm); int imm8 = -1; int num_bytes = 2; if (mod == 3) { const char* mnem = NULL; if (op == 0xD1) { imm8 = 1; switch (regop) { case edx: mnem = "rcl"; break; case edi: mnem = "sar"; break; case esp: mnem = "shl"; break; default: UnimplementedInstruction(); } } else if (op == 0xC1) { imm8 = *(data+2); num_bytes = 3; switch (regop) { case edx: mnem = "rcl"; break; case esp: mnem = "shl"; break; case ebp: mnem = "shr"; break; case edi: mnem = "sar"; break; default: UnimplementedInstruction(); } } else if (op == 0xD3) { switch (regop) { case esp: mnem = "shl"; break; case ebp: mnem = "shr"; break; case edi: mnem = "sar"; break; default: UnimplementedInstruction(); } } assert(mnem != NULL); AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm)); if (imm8 > 0) { AppendToBuffer("%d", imm8); } else { AppendToBuffer("cl"); } } else { UnimplementedInstruction(); } return num_bytes;}// Returns number of bytes used, including *data.int DisassemblerIA32::JumpShort(byte* data) { assert(*data == 0xEB); byte b = *(data+1); byte* dest = data + static_cast<int8_t>(b) + 2; AppendToBuffer("jmp %s", NameOfAddress(dest)); return 2;}// Returns number of bytes used, including *data.int DisassemblerIA32::JumpConditional(byte* data, const char* comment) { assert(*data == 0x0F); byte cond = *(data+1) & 0x0F; byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; const char* mnem = jump_conditional_mnem[cond]; AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); if (comment != NULL) { AppendToBuffer(", %s", comment); } return 6; // includes 0x0F}// Returns number of bytes used, including *data.int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { byte cond = *data & 0x0F; byte b = *(data+1); byte* dest = data + static_cast<int8_t>(b) + 2; const char* mnem = jump_conditional_mnem[cond]; AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); if (comment != NULL) { AppendToBuffer(", %s", comment); } return 2;}// Returns number of bytes used, including *data.int DisassemblerIA32::FPUInstruction(byte* data) { byte b1 = *data; byte b2 = *(data + 1); if (b1 == 0xD9) { const char* mnem = NULL; switch (b2) { case 0xE8: mnem = "fld1"; break; case 0xEE: mnem = "fldz"; break; case 0xE1: mnem = "fabs"; break; case 0xE0: mnem = "fchs"; break; case 0xF8: mnem = "fprem"; break; case 0xF5: mnem = "fprem1"; break; case 0xF7: mnem = "fincstp"; break; case 0xE4: mnem = "ftst"; break; } if (mnem != NULL) { AppendToBuffer("%s", mnem); return 2; } else if ((b2 & 0xF8) == 0xC8) { AppendToBuffer("fxch st%d", b2 & 0x7); return 2; } else { int mod, regop, rm; get_modrm(*(data+1), &mod, ®op, &rm); const char* mnem = "?"; switch (regop) { case eax: mnem = "fld_s"; break; case ebx: mnem = "fstp_s"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s ", mnem); int count = PrintRightOperand(data + 1); return count + 1; } } else if (b1 == 0xDD) { if ((b2 & 0xF8) == 0xC0) { AppendToBuffer("ffree st%d", b2 & 0x7); return 2; } else { int mod, regop, rm; get_modrm(*(data+1), &mod, ®op, &rm); const char* mnem = "?"; switch (regop) { case eax: mnem = "fld_d"; break; case ebx: mnem = "fstp_d"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s ", mnem); int count = PrintRightOperand(data + 1); return count + 1; } } else if (b1 == 0xDB) { int mod, regop, rm; get_modrm(*(data+1), &mod, ®op, &rm); const char* mnem = "?"; switch (regop) { case eax: mnem = "fild_s"; break; case edx: mnem = "fist_s"; break; case ebx: mnem = "fistp_s"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s ", mnem); int count = PrintRightOperand(data + 1); return count + 1; } else if (b1 == 0xDF) { if (b2 == 0xE0) { AppendToBuffer("fnstsw_ax"); return 2; } int mod, regop, rm; get_modrm(*(data+1), &mod, ®op, &rm); const char* mnem = "?"; switch (regop) { case ebp: mnem = "fild_d"; break; case edi: mnem = "fistp_d"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s ", mnem); int count = PrintRightOperand(data + 1); return count + 1; } else if (b1 == 0xDC || b1 == 0xDE) { bool is_pop = (b1 == 0xDE); if (is_pop && b2 == 0xD9) { AppendToBuffer("fcompp"); return 2; } const char* mnem = "FP0xDC"; switch (b2 & 0xF8) { case 0xC0: mnem = "fadd"; break; case 0xE8: mnem = "fsub"; break; case 0xC8: mnem = "fmul"; break; case 0xF8: mnem = "fdiv"; break; default: UnimplementedInstruction(); } AppendToBuffer("%s%s st%d", mnem, is_pop ? "p" : "", b2 & 0x7); return 2; } else if (b1 == 0xDA && b2 == 0xE9) { const char* mnem = "fucompp"; AppendToBuffer("%s", mnem); return 2; } AppendToBuffer("Unknown FP instruction"); return 2;}// Mnemonics for instructions 0xF0 byte.// Returns NULL if the instruction is not handled here.static const char* F0Mnem(byte f0byte) { switch (f0byte) { case 0xA2: return "cpuid"; case 0x31: return "rdtsc"; case 0xBE: return "movsx_b"; case 0xBF: return "movsx_w"; case 0xB6: return "movzx_b"; case 0xB7: return "movzx_w"; case 0xAF: return "imul"; case 0xA5: return "shld"; case 0xAD: return "shrd"; case 0xAB: return "bts"; default: return NULL; }}// Disassembled instruction '*instr' and writes it intro 'out_buffer'.int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, byte* instr) { tmp_buffer_pos_ = 0; // starting to write as position 0 byte* data = instr; // Check for hints. const char* branch_hint = NULL; // We use this two prefixes only with branch prediction if (*data == 0x3E /*ds*/) { branch_hint = "predicted taken"; data++; } else if (*data == 0x2E /*cs*/) { branch_hint = "predicted not taken"; data++; } bool processed = true; // Will be set to false if the current instruction // is not in 'instructions' table. const InstructionDesc& idesc = instruction_table.Get(*data); switch (idesc.type) { case ZERO_OPERANDS_INSTR: AppendToBuffer(idesc.mnem); data++; break; case TWO_OPERANDS_INSTR: data++; data += PrintOperands(idesc.mnem, idesc.op_order_, data); break; case JUMP_CONDITIONAL_SHORT_INSTR: data += JumpConditionalShort(data, branch_hint); break; case REGISTER_INSTR: AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); data++; break; case MOVE_REG_INSTR: { byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07), NameOfAddress(addr)); data += 5; break; } case CALL_JUMP_INSTR: { byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5; AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); data += 5; break; } case SHORT_IMMEDIATE_INSTR: { byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); AppendToBuffer("%s eax, %s", idesc.mnem, NameOfAddress(addr)); data += 5; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -