GNIDA.mediana.medi_disassemble C# (CSharp) Method

medi_disassemble() public method

public medi_disassemble ( long offset, INSTRUCTION &instr, DISASM_INOUT_PARAMS &param ) : UInt32
offset long
instr INSTRUCTION
param DISASM_INOUT_PARAMS
return UInt32
        public UInt32 medi_disassemble(long offset, ref INSTRUCTION instr, ref DISASM_INOUT_PARAMS param)
        {
            UInt32 len;
            UInt32 res;
            OPCODE_DESCRIPTOR opcode = new OPCODE_DESCRIPTOR();
            INTERNAL_DATA idata = new INTERNAL_DATA(0xFF);

            //Setup everything.
            //memset(instr, 0x0, sizeof(*instr));
            //memset(&idata, 0x0, sizeof(idata));
            //memset(idata.prefixes, 0xFF, sizeof(idata.prefixes));
            param.sf_prefixes_len = 0;
            param.errcode = 0;
            len = res = 0;
            //Lookup opcode.
            res = parse_opcode(offset, ref opcode, ref instr, idata, ref param);
            if (idata.severe_err != ERRS.ERR_OK)
            {
                param.errcode = idata.severe_err;
                return 0;
            }
            len += res;

            if (len > MAX_INSTRUCTION_LEN)
            {
            param.errcode = ERRS.ERR_TOO_LONG;
            return 0;
            }

            get_address_size(ref instr, idata.prefixes, param.mode);

            //Parse MODRM and SIB bytes.
            len += parse_modrm_sib(offset + len, ref instr, opcode);
            if (len > MAX_INSTRUCTION_LEN)
            {
            param.errcode = ERRS.ERR_TOO_LONG;
            return 0;
            }

            //Copy flags, eflags, id, groups.
            copy_eflags(ref instr, ref opcode);
            copy_instr_flags(ref instr, ref opcode);
            instr.id = opcode.id;
            instr.groups = opcode.groups;

            //Parse mnemonic.
            parse_mnemonic(opcode, instr, idata, param.mode);
            if (idata.severe_err != ERRS.ERR_OK)
            {
            param.errcode = idata.severe_err;
            return 0;
            }

            //Deal with operands.
            res = parse_operand(offset, offset + len, opcode.ops[0], instr, 0, idata, param.mode);
            if (idata.severe_err != ERRS.ERR_OK)
            {
            param.errcode = idata.severe_err;
            return 0;
            }
            len += res;
            if (len > MAX_INSTRUCTION_LEN)
            {
            param.errcode = ERRS.ERR_TOO_LONG;
            return 0;
            }

            res = parse_operand(offset, offset + len, opcode.ops[1], instr, 1, idata, param.mode);
            if (idata.severe_err != ERRS.ERR_OK)
            {
            param.errcode = idata.severe_err;
            return 0;
            }
            len += res;
            if (len > MAX_INSTRUCTION_LEN)
            {
            param.errcode = ERRS.ERR_TOO_LONG;
            return 0;
            }

            res = parse_operand(offset, offset + len, opcode.ops[2], instr, 2, idata, param.mode);
            if (idata.severe_err != ERRS.ERR_OK)
            {
            param.errcode = idata.severe_err;
            return 0;
            }
            len += res;
            if (len > MAX_INSTRUCTION_LEN)
            {
            param.errcode = ERRS.ERR_TOO_LONG;
            return 0;
            }

            //Do postprocessing if necessary.
            if ((opcode.props & PROP_POST_PROC)!=0)
            {
            res = postprocs[opcode.props >> POST_PROC_SHIFT](offset, offset, ref instr, idata, param.mode);
            if (idata.severe_err != ERRS.ERR_OK)
            {
            param.errcode = idata.severe_err;
            return 0;
            }
            if (res>0)
            {
            len = res;
            if (len > MAX_INSTRUCTION_LEN)
            {
                param.errcode = ERRS.ERR_TOO_LONG;
                return 0;
            }
            }
            }

            //Check if REX is superfluous.
            if ((param.mode == DISMODE.DISASSEMBLE_MODE_64) && (idata.is_rex_used != 0))
            add_sf_prefix_value(idata.prefixes, PREF_REX_INDEX, instr.rex, ref instr, ref param);
            //Check if segment prefix is superfluous.
            check_seg_sf_prefixes(instr, idata.prefixes, param);
            //Check if opsize is superfluous.
            if ((idata.is_opsize_used!=0) && idata.prefixes[PREF_OPSIZE_INDEX] != 0xFF)
            add_sf_prefix(idata.prefixes, PREF_OPSIZE_INDEX, ref instr, ref param);
            //Check if addrsize is superfluous.
            if ((idata.is_addrsize_used!=0) && idata.prefixes[PREF_ADDRSIZE_INDEX] != 0xFF)
            add_sf_prefix(idata.prefixes, PREF_ADDRSIZE_INDEX, ref instr, ref param);

            //Convert prefixes to output representation.
            convert_prefixes(instr, idata.prefixes);

            //Copy error if exists.
            param.errcode = idata.err;

            //And post checks.
            if ((param.arch & opcode.arch)!=0)
            param.errcode = ERRS.ERR_ANOT_ARCH;//error: another architecture.
            else if ( ((instr.prefixes & INSTR_PREFIX_LOCK)!=0) && ((opcode.props & PROP_LOCK)==0) )
            param.errcode = ERRS.ERR_NON_LOCKABLE;//error: prefix lock non-lockable instruction.
            else if (((opcode.props & PROP_I64) != 0) && (param.mode == DISMODE.DISASSEMBLE_MODE_64))
            param.errcode = ERRS.ERR_16_32_ONLY;//error: instruction is 16/32bit mode only.
            else if (((opcode.props & PROP_O64) != 0) && (param.mode != DISMODE.DISASSEMBLE_MODE_64))
            param.errcode = ERRS.ERR_64_ONLY;//error: instruction is 64bit mode only.

            apply_disasm_options(ref instr, len, param);
            instr.bytes = assembly.Image.ReadBytes(offset, (int)len);

            instr.Addr = (ulong)offset;
            return len;
        }