public ldasm_data ldasm(byte[] code, int offset, bool is64) { ldasm_data ldasm = new ldasm_data(); int p = offset; byte s = 0, op = 0, f = 0; byte rexw = 0, pr_66 = 0, pr_67 = 0; if (code == null) { return(ldasm); } /* phase 1: parse prefixies */ while ((cflags(code[p]) & OP_PREFIX) == OP_PREFIX) { if (code[p] == 0x66) { pr_66 = 1; } if (code[p] == 0x67) { pr_67 = 1; } p++; s++; ldasm.flags |= F_PREFIX; if (s == 15) { ldasm.flags |= F_INVALID; ldasm.size = s; return(ldasm); } } /* parse REX prefix */ if (is64 && code[p] >> 4 == 4) { ldasm.rex = code[p]; rexw = (byte)((ldasm.rex >> 3) & 1); ldasm.flags |= F_REX; p++; s++; } /* can be only one REX prefix */ if (is64 && code[p] >> 4 == 4) { ldasm.flags |= F_INVALID; s++; ldasm.size = s; return(ldasm); } /* phase 2: parse opcode */ ldasm.opcd_offset = p; ldasm.opcd_size = 1; op = code[p++]; s++; /* is 2 byte opcede? */ if (op == 0x0F) { op = code[p++]; s++; ldasm.opcd_size++; f = cflags_ex(op); if ((f & OP_INVALID) == OP_INVALID) { ldasm.flags |= F_INVALID; ldasm.size = s; return(ldasm); } /* for SSE instructions */ if ((f & OP_EXTENDED) == OP_EXTENDED) { op = code[p++]; s++; ldasm.opcd_size++; } } else { f = cflags(op); /* pr_66 = pr_67 for opcodes A0-A3 */ if (op >= 0xA0 && op <= 0xA3) { pr_66 = pr_67; } } /* phase 3: parse ModR/M, SIB and DISP */ if ((f & OP_MODRM) == OP_MODRM) { byte mod = (byte)(code[p] >> 6); byte ro = (byte)((code[p] & 0x38) >> 3); byte rm = (byte)(code[p] & 7); ldasm.modrm = code[p++]; s++; ldasm.flags |= F_MODRM; /* in F6,F7 opcodes immediate data present if R/O == 0 */ if (op == 0xF6 && (ro == 0 || ro == 1)) { f |= OP_DATA_I8; } if (op == 0xF7 && (ro == 0 || ro == 1)) { f |= OP_DATA_I16_I32_I64; } /* is SIB byte exist? */ if (mod != 3 && rm == 4 && !((!is64) && (pr_67 == 1))) { ldasm.sib = code[p++]; s++; ldasm.flags |= F_SIB; /* if base == 5 and mod == 0 */ if ((ldasm.sib & 7) == 5 && mod == 0) { ldasm.disp_size = 4; } } switch (mod) { case 0: if (is64) { if (rm == 5) { ldasm.disp_size = 4; if (is64) { ldasm.flags |= F_RELATIVE; } } } else if (pr_67 == 1) { if (rm == 6) { ldasm.disp_size = 2; } } else { if (rm == 5) { ldasm.disp_size = 4; } } break; case 1: ldasm.disp_size = 1; break; case 2: if (is64) { ldasm.disp_size = 4; } else if (pr_67 == 1) { ldasm.disp_size = 2; } else { ldasm.disp_size = 4; } break; } if (ldasm.disp_size > 0) { ldasm.disp_offset = p; p += ldasm.disp_size; s += ldasm.disp_size; ldasm.flags |= F_DISP; } } /* phase 4: parse immediate data */ if (rexw > 0 && (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64) { ldasm.imm_size = 8; } else if ((f & OP_DATA_I16_I32) == OP_DATA_I16_I32 || (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64) { ldasm.imm_size = (byte)(4 - (pr_66 << 1)); } /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */ ldasm.imm_size += (byte)(f & 3); if (ldasm.imm_size > 0) { s += ldasm.imm_size; ldasm.imm_offset = p; ldasm.flags |= F_IMM; if ((f & OP_RELATIVE) == OP_RELATIVE) { ldasm.flags |= F_RELATIVE; } } /* instruction is too long */ if (s > 15) { ldasm.flags |= F_INVALID; } ldasm.size = s; return(ldasm); }
public ldasm_data ldasm(byte[] code, int offset, bool is64) { ldasm_data ldasm = new ldasm_data(); int p = offset; byte s = 0, op = 0, f = 0; byte rexw = 0, pr_66 = 0, pr_67 = 0; if (code == null) return ldasm; /* phase 1: parse prefixies */ while ((cflags(code[p]) & OP_PREFIX) == OP_PREFIX) { if (code[p] == 0x66) { pr_66 = 1; } if (code[p] == 0x67) { pr_67 = 1; } p++; s++; ldasm.flags |= F_PREFIX; if (s == 15) { ldasm.flags |= F_INVALID; ldasm.size = s; return ldasm; } } /* parse REX prefix */ if (is64 && code[p] >> 4 == 4) { ldasm.rex = code[p]; rexw = (byte)((ldasm.rex >> 3) & 1); ldasm.flags |= F_REX; p++; s++; } /* can be only one REX prefix */ if (is64 && code[p] >> 4 == 4) { ldasm.flags |= F_INVALID; s++; ldasm.size = s; return ldasm; } /* phase 2: parse opcode */ ldasm.opcd_offset = p; ldasm.opcd_size = 1; op = code[p++]; s++; /* is 2 byte opcede? */ if (op == 0x0F) { op = code[p++]; s++; ldasm.opcd_size++; f = cflags_ex(op); if ((f & OP_INVALID) == OP_INVALID) { ldasm.flags |= F_INVALID; ldasm.size = s; return ldasm; } /* for SSE instructions */ if ((f & OP_EXTENDED) == OP_EXTENDED) { op = code[p++]; s++; ldasm.opcd_size++; } } else { f = cflags(op); /* pr_66 = pr_67 for opcodes A0-A3 */ if (op >= 0xA0 && op <= 0xA3) pr_66 = pr_67; } /* phase 3: parse ModR/M, SIB and DISP */ if ((f & OP_MODRM) == OP_MODRM) { byte mod = (byte)(code[p] >> 6); byte ro = (byte)((code[p] & 0x38) >> 3); byte rm = (byte)(code[p] & 7); ldasm.modrm = code[p++]; s++; ldasm.flags |= F_MODRM; /* in F6,F7 opcodes immediate data present if R/O == 0 */ if (op == 0xF6 && (ro == 0 || ro == 1)) f |= OP_DATA_I8; if (op == 0xF7 && (ro == 0 || ro == 1)) f |= OP_DATA_I16_I32_I64; /* is SIB byte exist? */ if (mod != 3 && rm == 4 && !((!is64) && (pr_67 == 1))) { ldasm.sib = code[p++]; s++; ldasm.flags |= F_SIB; /* if base == 5 and mod == 0 */ if ((ldasm.sib & 7) == 5 && mod == 0) { ldasm.disp_size = 4; } } switch (mod) { case 0: if (is64) { if (rm == 5) { ldasm.disp_size = 4; if (is64) ldasm.flags |= F_RELATIVE; } } else if (pr_67 == 1) { if (rm == 6) ldasm.disp_size = 2; } else { if (rm == 5) ldasm.disp_size = 4; } break; case 1: ldasm.disp_size = 1; break; case 2: if (is64) ldasm.disp_size = 4; else if (pr_67 == 1) ldasm.disp_size = 2; else ldasm.disp_size = 4; break; } if (ldasm.disp_size > 0) { ldasm.disp_offset = p; p += ldasm.disp_size; s += ldasm.disp_size; ldasm.flags |= F_DISP; } } /* phase 4: parse immediate data */ if (rexw > 0 && (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64) ldasm.imm_size = 8; else if ((f & OP_DATA_I16_I32) == OP_DATA_I16_I32 || (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64) ldasm.imm_size = (byte)(4 - (pr_66 << 1)); /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */ ldasm.imm_size += (byte)(f & 3); if (ldasm.imm_size > 0) { s += ldasm.imm_size; ldasm.imm_offset = p; ldasm.flags |= F_IMM; if ((f & OP_RELATIVE) == OP_RELATIVE) ldasm.flags |= F_RELATIVE; } /* instruction is too long */ if (s > 15) ldasm.flags |= F_INVALID; ldasm.size = s; return ldasm; }