Ejemplo n.º 1
0
        public static Elf64_Sym Load(EndianImageReader rdr)
        {
            var sym = new Elf64_Sym();

            sym.st_name  = rdr.ReadUInt32();
            sym.st_info  = rdr.ReadByte();
            sym.st_other = rdr.ReadByte();
            sym.st_shndx = rdr.ReadUInt16();
            sym.st_value = rdr.ReadUInt64();
            sym.st_size  = rdr.ReadUInt64();
            return(sym);
        }
Ejemplo n.º 2
0
        public void LoadElfIdentification(EndianImageReader rdr)
        {
            var elfMagic = rdr.ReadBeInt32();

            if (elfMagic != ELF_MAGIC)
            {
                throw new BadImageFormatException("File is not in ELF format.");
            }
            this.fileClass   = rdr.ReadByte();
            this.endianness  = rdr.ReadByte();
            this.fileVersion = rdr.ReadByte();
            this.osAbi       = rdr.ReadByte();
        }
Ejemplo n.º 3
0
        public void VisitPointer(Pointer ptr)
        {
            switch (ptr.Size)
            {
            case 2:
                fmt.WriteKeyword("dw");
                fmt.Write("\t");
                fmt.Write(string.Format("0x{0:X4}", rdr.ReadByte()));
                fmt.WriteLine();
                return;

            case 4:
                fmt.WriteKeyword("dd");
                fmt.Write("\t");
                fmt.Write(string.Format("0x{0:X8}", rdr.ReadUInt32()));
                fmt.WriteLine();
                return;

            case 8:
                fmt.WriteKeyword("dq");
                fmt.Write("\t");
                fmt.Write(string.Format("0x{0:X16}", rdr.ReadUInt64()));
                fmt.WriteLine();
                return;
            }
        }
Ejemplo n.º 4
0
            /// <summary>
            /// Paints a line of the memory control, starting with the address.
            /// </summary>
            /// <remarks>
            /// The strategy is to find any items present at the current address, and try
            /// to paint as many adjacent items as possible.
            /// </remarks>
            /// <param name="g"></param>
            /// <param name="rc"></param>
            /// <param name="rdr"></param>
            private Address PaintLine(Graphics g, Rectangle rc, EndianImageReader rdr, Point ptAddr, bool render)
            {
                StringBuilder sxbCode = new StringBuilder(" ");
                var           abCode  = new List <byte>();

                // Draw the address part.

                rc.X = 0;
                string s  = string.Format("{0}", rdr.Address);
                int    cx = (int)g.MeasureString(s + "X", ctrl.Font, rc.Width, StringFormat.GenericTypographic).Width;

                if (!render && new Rectangle(rc.X, rc.Y, cx, rc.Height).Contains(ctrl.ptDown))
                {
                    return(rdr.Address);
                }
                else
                {
                    g.FillRectangle(this.defaultTheme.Background, rc.X, rc.Y, cx, rc.Height);
                    g.DrawString(s, ctrl.Font, defaultTheme.Foreground, rc.X, rc.Y, StringFormat.GenericTypographic);
                }
                cx -= cellSize.Width / 2;
                rc  = new Rectangle(cx, rc.Top, rc.Width - cx, rc.Height);

                uint  rowBytesLeft   = ctrl.cbRow;
                ulong linearSelected = ctrl.addrSelected != null?ctrl.addrSelected.ToLinear() : ~0UL;

                ulong linearAnchor = ctrl.addrAnchor != null?ctrl.addrAnchor.ToLinear() : ~0UL;

                ulong linearBeginSelection = Math.Min(linearSelected, linearAnchor);
                ulong linearEndSelection   = Math.Max(linearSelected, linearAnchor);

                do
                {
                    Address addr   = rdr.Address;
                    ulong   linear = addr.ToLinear();

                    ImageMapItem item;
                    ulong        cbIn = 0;
                    if (ctrl.ImageMap.TryFindItem(addr, out item))
                    {
                        cbIn = (linear - item.Address.ToLinear()); // # of bytes 'inside' the block we are.
                    }
                    uint cbToDraw = 16;                            // item.Size - cbIn;

                    // See if the chunk goes off the edge of the line. If so, clip it.
                    if (cbToDraw > rowBytesLeft)
                    {
                        cbToDraw = rowBytesLeft;
                    }

                    // Now paint the bytes in this span.

                    for (int i = 0; i < cbToDraw; ++i)
                    {
                        Address addrByte = rdr.Address;
                        ctrl.ImageMap.TryFindItem(addrByte, out item);
                        bool isSelected = linearBeginSelection <= addrByte.ToLinear() && addrByte.ToLinear() <= linearEndSelection;
                        bool isCursor   = addrByte.ToLinear() == linearSelected;
                        if (rdr.IsValid)
                        {
                            byte b = rdr.ReadByte();
                            s = string.Format("{0:X2}", b);
                            abCode.Add(b);
                        }
                        else
                        {
                            s = "  ";
                            abCode.Add(0x20);   //$BUG: encoding? What about Ebcdic?
                            rdr.Offset += 1;
                        }

                        cx = cellSize.Width * 3;
                        Rectangle rcByte = new Rectangle(
                            rc.Left,
                            rc.Top,
                            cx,
                            rc.Height);

                        if (!render && rcByte.Contains(ptAddr))
                        {
                            return(addrByte);
                        }

                        var theme = GetBrushTheme(item, isSelected);
                        g.FillRectangle(theme.Background, rc.Left, rc.Top, cx, rc.Height);
                        if (!isSelected &&
                            theme.StartMarker != null &&
                            item != null &&
                            addrByte.ToLinear() == item.Address.ToLinear())
                        {
                            var pts = new Point[]
                            {
                                rc.Location,
                                rc.Location,
                                rc.Location,
                            };
                            pts[1].Offset(4, 0);
                            pts[2].Offset(0, 4);
                            g.FillClosedCurve(theme.StartMarker, pts);
                        }
                        g.DrawString(s, ctrl.Font, theme.Foreground, rc.Left + cellSize.Width / 2, rc.Top, StringFormat.GenericTypographic);
                        if (isCursor)
                        {
                            ControlPaint.DrawFocusRectangle(g, rc);
                        }
                        rc = new Rectangle(rc.X + cx, rc.Y, rc.Width - cx, rc.Height);
                    }
                    rowBytesLeft -= cbToDraw;
                } while (rowBytesLeft > 0);

                if (render)
                {
                    g.FillRectangle(this.defaultTheme.Background, rc);
                    sxbCode.Append(RenderCode(abCode.ToArray()));
                    g.DrawString(sxbCode.ToString(), ctrl.Font, this.defaultTheme.Foreground, rc.X + cellSize.Width, rc.Top, StringFormat.GenericTypographic);
                }
                return(null);
            }
Ejemplo n.º 5
0
        /// <summary>
        /// Apply relocations to a segment.
        /// </summary>
        private bool ApplyRelocations(EndianImageReader rdr, int cRelocations, NeSegment seg)
        {
            Address           address = null;
            NeRelocationEntry rep;

            Debug.Print("== Relocating segment {0}", seg.Address);
            for (int i = 0; i < cRelocations; i++)
            {
                rep = new NeRelocationEntry
                {
                    address_type    = (NE_RADDR)rdr.ReadByte(),
                    relocation_type = (NE_RELTYPE)rdr.ReadByte(),
                    offset          = rdr.ReadLeUInt16(),
                    target1         = rdr.ReadLeUInt16(),
                    target2         = rdr.ReadLeUInt16(),
                };
                Debug.Print("  {0}", WriteRelocationEntry(rep));

                // Get the target address corresponding to this entry.

                // If additive, there is no target chain list. Instead, add source
                //  and target.
                bool additive = (rep.relocation_type & NE_RELTYPE.ADDITIVE) != 0;
                Tuple <Address, ImportReference> impRef;
                uint   lp;
                string module = "";
                switch (rep.relocation_type & (NE_RELTYPE)3)
                {
                case NE_RELTYPE.ORDINAL:
                    module = moduleNames[rep.target1 - 1];
                    // Synthesize an import
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new OrdinalImportReference(address, module, rep.target2, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.NAME:
                    module = moduleNames[rep.target1 - 1];
                    uint offName      = lfaNew + this.offImportedNamesTable + rep.target2;
                    var  nameRdr      = new LeImageReader(RawImage, offName);
                    byte fnNameLength = nameRdr.ReadByte();
                    var  abFnName     = nameRdr.ReadBytes(fnNameLength);
                    // Synthesize the import.
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        string fnName = Encoding.ASCII.GetString(abFnName);
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new NamedImportReference(address, module, fnName, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.INTERNAL:
                    if ((rep.target1 & 0xff) == 0xff)
                    {
                        address = this.entryPoints[rep.target2 - 1].Address;
                    }
                    else
                    {
                        address = segments[rep.target1 - 1].Address + rep.target2;
                    }
                    Debug.Print("    {0}: {1:X4}:{2:X4} {3}",
                                i + 1,
                                address.Selector.Value,
                                address.Offset,
                                "");
                    break;

                case NE_RELTYPE.OSFIXUP:
                    /* Relocation type 7:
                     *
                     *    These appear to be used as fixups for the Windows
                     * floating point emulator.  Let's just ignore them and
                     * try to use the hardware floating point.  Linux should
                     * successfully emulate the coprocessor if it doesn't
                     * exist.
                     */
                    /*
                     * TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                     *   i + 1, rep->relocation_type, rep->offset,
                     *   rep->target1, rep->target2,
                     *   NE_GetRelocAddrName( rep->address_type, additive ) );
                     */
                    continue;
                }
                ushort offset = rep.offset;

                // Apparently, high bit of address_type is sometimes set;
                // we ignore it for now.
                if (rep.address_type > NE_RADDR.OFFSET32)
                {
                    listener.Error(
                        string.Format(
                            "Module {0}: unknown relocation address type {1:X2}. Please report",
                            module, rep.address_type));
                    return(false);
                }

                if (additive)
                {
                    var sp = seg.Address + offset;
                    Debug.Print("    {0} (contains: {1:X4})", sp, mem.ReadLeUInt16(sp));
                    byte   b;
                    ushort w;
                    switch (rep.address_type & (NE_RADDR)0x7f)
                    {
                    case NE_RADDR.LOWBYTE:
                        b = mem.ReadByte(sp);
                        mem.WriteByte(sp, (byte)(b + address.Offset));
                        break;

                    case NE_RADDR.OFFSET16:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        break;

                    case NE_RADDR.POINTER32:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                        break;

                    case NE_RADDR.SELECTOR:
                        // Borland creates additive records with offset zero. Strange, but OK.
                        w = mem.ReadLeUInt16(sp);
                        if (w != 0)
                        {
                            listener.Error(string.Format("Additive selector to {0:X4}. Please report.", w));
                        }
                        else
                        {
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                        }
                        break;

                    default:
                        goto unknown;
                    }
                }
                else
                {
                    // Non-additive fixup.
                    do
                    {
                        var    sp          = seg.Address + offset;
                        ushort next_offset = mem.ReadLeUInt16(sp);
                        Debug.Print("    {0} (contains: {1:X4})", sp, next_offset);
                        switch (rep.address_type & (NE_RADDR)0x7f)
                        {
                        case NE_RADDR.LOWBYTE:
                            mem.WriteByte(sp, (byte)address.Offset);
                            break;

                        case NE_RADDR.OFFSET16:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            break;

                        case NE_RADDR.POINTER32:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                            break;

                        case NE_RADDR.SELECTOR:
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                            break;

                        default:
                            goto unknown;
                        }
                        if (next_offset == offset)
                        {
                            break;                         // avoid infinite loop
                        }
                        if (next_offset >= seg.Alloc)
                        {
                            break;
                        }
                        offset = next_offset;
                    } while (offset != 0xffff);
                }
            }
            return(true);

unknown:
            listener.Warn("{0}: unknown ADDR TYPE {1},  " +
                          "TYPE {2},  OFFSET {3:X4},  TARGET {4:X4} {5:X4}",
                          seg.Address.Selector, rep.address_type, rep.relocation_type,
                          rep.offset, rep.target1, rep.target2);
            return(false);
        }
Ejemplo n.º 6
0
        public void ReadOptionalHeader(EndianImageReader rdr, short expectedMagic)
        {
            if (optionalHeaderSize <= 0)
            {
                throw new BadImageFormatException("Optional header size should be larger than 0 in a PE executable image file.");
            }

            short magic = rdr.ReadLeInt16();

            if (magic != expectedMagic)
            {
                throw new BadImageFormatException("Not a valid PE Header.");
            }
            rdr.ReadByte();                     // Linker major version
            rdr.ReadByte();                     // Linker minor version
            rdr.ReadLeUInt32();                 // code size (== .text section size)
            rdr.ReadLeUInt32();                 // size of initialized data
            rdr.ReadLeUInt32();                 // size of uninitialized data
            rvaStartAddress = rdr.ReadLeUInt32();
            uint rvaBaseOfCode = rdr.ReadLeUInt32();

            preferredBaseOfImage = innerLoader.ReadPreferredImageBase(rdr);
            rdr.ReadLeUInt32();                         // section alignment
            rdr.ReadLeUInt32();                         // file alignment
            rdr.ReadLeUInt16();                         // OS major version
            rdr.ReadLeUInt16();                         // OS minor version
            rdr.ReadLeUInt16();                         // Image major version
            rdr.ReadLeUInt16();                         // Image minor version
            rdr.ReadLeUInt16();                         // Subsystem major version
            rdr.ReadLeUInt16();                         // Subsystem minor version
            rdr.ReadLeUInt32();                         // reserved
            uint   sizeOfImage   = rdr.ReadLeUInt32();
            uint   sizeOfHeaders = rdr.ReadLeUInt32();
            uint   checksum      = rdr.ReadLeUInt32();
            ushort subsystem     = rdr.ReadLeUInt16();
            ushort dllFlags      = rdr.ReadLeUInt16();
            var    stackReserve  = innerLoader.ReadWord(rdr);
            var    stackCommit   = innerLoader.ReadWord(rdr);
            var    heapReserve   = innerLoader.ReadWord(rdr);
            var    heapCommit    = innerLoader.ReadWord(rdr);

            rdr.ReadLeUInt32();                                 // loader flags
            uint dictionaryCount = rdr.ReadLeUInt32();

            if (dictionaryCount == 0)
            {
                return;
            }
            this.rvaExportTable  = rdr.ReadLeUInt32();
            this.sizeExportTable = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaImportTable = rdr.ReadLeUInt32();
            uint importTableSize = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaResources = rdr.ReadLeUInt32();             // resource address
            rdr.ReadLeUInt32();                                 // resource size

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaExceptionTable  = rdr.ReadLeUInt32();                       // exception address
            this.sizeExceptionTable = rdr.ReadLeUInt32();                       // exception size

            if (--dictionaryCount == 0)
            {
                return;
            }
            rdr.ReadLeUInt32();                                 // certificate address
            rdr.ReadLeUInt32();                                 // certificate size

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaBaseRelocationTable  = rdr.ReadLeUInt32();
            this.sizeBaseRelocationTable = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaDebug = rdr.ReadLeUInt32();
            uint cbDebug  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaArchitecture = rdr.ReadLeUInt32();
            uint cbArchitecture  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaGlobalPointer = rdr.ReadLeUInt32();
            uint cbGlobalPointer  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaTls = rdr.ReadLeUInt32();
            uint cbTls  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaLoadConfig = rdr.ReadLeUInt32();
            uint cbLoadConfig  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaBoundImport = rdr.ReadLeUInt32();
            uint cbBoundImport  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaIat = rdr.ReadLeUInt32();
            uint cbIat  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaDelayImportDescriptor = rdr.ReadLeUInt32();
            uint cbDelayImportDescriptor = rdr.ReadLeUInt32();
        }
Ejemplo n.º 7
0
        public override CilInstruction DisassembleInstruction()
        {
            if (!rdr.IsValid)
            {
                return(null);
            }
            var addr   = rdr.Address;
            var opcode = rdr.ReadByte();

            instr = new CilInstruction
            {
                Address  = addr,
                Operands = MachineInstruction.NoOperands,
            };
            switch (opcode)
            {
                #region OPCODES
            case 0x00: instr.Opcode = OpCodes.Nop; break;

            case 0x01: instr.Opcode = OpCodes.Break; break;

            case 0x02: instr.Opcode = OpCodes.Ldarg_0; break;

            case 0x03: instr.Opcode = OpCodes.Ldarg_1; break;

            case 0x04: instr.Opcode = OpCodes.Ldarg_2; break;

            case 0x05: instr.Opcode = OpCodes.Ldarg_3; break;

            case 0x06: instr.Opcode = OpCodes.Ldloc_0; break;

            case 0x07: instr.Opcode = OpCodes.Ldloc_1; break;

            case 0x08: instr.Opcode = OpCodes.Ldloc_2; break;

            case 0x09: instr.Opcode = OpCodes.Ldloc_3; break;

            case 0x0A: instr.Opcode = OpCodes.Stloc_0; break; //  Pop a value from stack into local variable 0.

            case 0x0B: instr.Opcode = OpCodes.Stloc_1; break; //Pop a value from stack into local variable 1.

            case 0x0C: instr.Opcode = OpCodes.Stloc_2; break; //Pop a value from stack into local variable 2.

            case 0x0D: instr.Opcode = OpCodes.Stloc_3; break; //Pop a value from stack into local variable 3.

            case 0x0E:                                        //Load argument numbered num onto the stack, short form.
                instr.Opcode  = OpCodes.Ldarg_S;              // <uint8 (num)>
                instr.Operand = rdr.ReadByte();
                break;

            case 0x0F:
                instr.Opcode  = OpCodes.Ldarga_S; // <uint8 (argNum)>
                instr.Operand = rdr.ReadByte();
                break;

            //Fetch the address of argument argNum, short form.
            case 0x10:

                instr.Opcode  = OpCodes.Starg_S; // .s <uint8 (num)>
                instr.Operand = rdr.ReadByte();
                break;

            //Store value to the argument numbered num, short form.
            case 0x11:

                instr.Opcode  = OpCodes.Ldloc_S; // <uint8 (indx)>
                instr.Operand = rdr.ReadByte();
                break;

            //Load local variable of index indx onto stack, short form.
            case 0x12:
                instr.Opcode  = OpCodes.Ldloca_S;   // .s <uint8 (indx)>
                instr.Operand = rdr.ReadByte();
                break;

            //Load address of local variable with index indx, short form.
            case 0x13:

                instr.Opcode  = OpCodes.Stloc_S; // <uint8 (indx)>
                instr.Operand = rdr.ReadByte();
                break;

            //Pop a value from stack into local variable indx, short form.
            case 0x14: instr.Opcode = OpCodes.Ldnull; break;    //Push a null reference on the stack.

            case 0x15: instr.Opcode = OpCodes.Ldc_I4_M1; break; //Push -1 onto the stack as int32.

            case 0x16: instr.Opcode = OpCodes.Ldc_I4_0; break;

            case 0x17: instr.Opcode = OpCodes.Ldc_I4_1; break;  //Push 1 onto the stack as int32.

            case 0x18: instr.Opcode = OpCodes.Ldc_I4_2; break;  //Push 2 onto the stack as int32.

            case 0x19: instr.Opcode = OpCodes.Ldc_I4_3; break;  //Push 3 onto the stack as int32.

            case 0x1A:
                instr.Opcode = OpCodes.Ldc_I4_4;
                break;

            //Push 4 onto the stack as int32.
            case 0x1B:
                instr.Opcode = OpCodes.Ldc_I4_5;
                break;

            //Push 5 onto the stack as int32.
            case 0x1C:
                instr.Opcode = OpCodes.Ldc_I4_6;
                break;

            //Push 6 onto the stack as int32.
            case 0x1D:
                instr.Opcode = OpCodes.Ldc_I4_7;
                break;

            //Push 7 onto the stack as int32.
            case 0x1E:
                instr.Opcode = OpCodes.Ldc_I4_8;
                break;

            //Push 8 onto the stack as int32.
            case 0x1F:
                instr.Opcode  = OpCodes.Ldc_I4_S;   // <int8 (num)>
                instr.Operand = rdr.ReadSByte();
                break;

            //Push num onto the stack as int32, short form.
            case 0x20:
                instr.Opcode  = OpCodes.Ldc_I4;// <int32 (num)>
                instr.Operand = rdr.ReadLeInt32();
                break;

            //Push num of type int32 onto the stack as int32.
            case 0x21:
                instr.Opcode  = OpCodes.Ldc_I8;// <int64 (num)>
                instr.Operand = rdr.ReadLeInt64();
                break;

            //Push num of type int64 onto the stack as int64.
            case 0x22:
                instr.Opcode  = OpCodes.Ldc_R4;// <float32 (num)>
                instr.Operand = rdr.ReadLeUInt64();
                break;

            //Push num of type float32 onto the stack as F.
            case 0x23:
                instr.Opcode  = OpCodes.Ldc_R8; // <float64 (num)>
                instr.Operand = rdr.ReadLeUInt64();
                break;

            //Push num of type float64 onto the stack as F.
            case 0x25: instr.Opcode = OpCodes.Dup; break;

            //Duplicate the value on the top of the stack.
            case 0x26: instr.Opcode = OpCodes.Pop; break; //Pop value from the stack.

            case 0x27:
                instr.Opcode = OpCodes.Jmp;// <method>
                break;

            //Exit current method and jump to the specified method.
            case 0x28:
                instr.Opcode = OpCodes.Call;// <method>
                break;

            //Call method described by method.
            case 0x29:
                instr.Opcode = OpCodes.Calli;// <callsitedescr>
                break;

            //Call method indicated on the stack with arguments described by callsitedescr.
            case 0x2A: instr.Opcode = OpCodes.Ret; break; //Return from method, possibly with a value.

            case 0x2B:
                instr.Opcode = OpCodes.Br_S; // <int8 (target)>
                break;

            //Branch to target, short form.
            case 0x2C:
                instr.Opcode = OpCodes.Brfalse_S;// <int8 (target)>
                break;

            //Branch to target if value is zero (false), short form.
            case 0x2D:
                instr.Opcode = OpCodes.Brtrue_S; // <int8 (target)>
                break;

            //Branch to target if value is non-zero (true), short form.
            case 0x2E:
                instr.Opcode = OpCodes.Beq_S;  //.s <int8 (target)>
                break;

            //Branch to target if equal, short form.
            case 0x2F:
                instr.Opcode = OpCodes.Bge_S; //.s <int8 (target)>
                break;

            //Branch to target if greater than or equal to, short form.
            case 0x30:
                instr.Opcode = OpCodes.Bgt_S;   // .s <int8 (target)>
                break;

            //Branch to target if greater than, short form.
            case 0x31:
                instr.Opcode = OpCodes.Ble_S; // .s <int8 (target)>
                break;

            //Branch to target if less than or equal to, short form.
            case 0x32:
                instr.Opcode = OpCodes.Blt_S; //.s <int8 (target)>
                break;

            //Branch to target if less than, short form.
            case 0x33:
                instr.Opcode = OpCodes.Bne_Un_S;//.un.s <int8 (target)>
                break;

            //Branch to target if unequal or unordered, short form.
            case 0x34:
                instr.Opcode = OpCodes.Bge_Un_S;// <int8 (target)>
                break;

            //Branch to target if greater than or equal to (unsigned or unordered), short form
            case 0x35:
                instr.Opcode = OpCodes.Bgt_Un_S;// <int8 (target)>
                break;

            //Branch to target if greater than (unsigned or unordered), short form.
            case 0x36:
                instr.Opcode = OpCodes.Ble_Un_S;// <int8 (target)>
                break;

            //Branch to target if less than or equal to (unsigned or unordered), short form
            case 0x37:
                instr.Opcode = OpCodes.Blt_Un_S;//.un.s <int8 (target)>
                break;

            //Branch to target if less than (unsigned or unordered), short form.
            case 0x38:
                instr.Opcode = OpCodes.Br;// <int32 (target)>
                break;

            //Branch to target.
            case 0x39:
                instr.Opcode = OpCodes.Brfalse;// <int32 (target)>
                break;

            //Branch to target if value is zero (alias for brfalse).
            case 0x3A:
                instr.Opcode = OpCodes.Brtrue;// <int32 (target)>
                break;

            //Branch to target if value is non-zero (true).
            case 0x3B:
                instr.Opcode = OpCodes.Beq;// <int32 (target)>
                break;

            //Branch to target if equal.
            case 0x3C:
                instr.Opcode = OpCodes.Bge;// <int32 (target)>
                break;

            //Branch to target if greater than or equal to.
            case 0x3D:
                instr.Opcode = OpCodes.Bgt; // <int32 (target)>
                break;

            //Branch to target if greater than.
            case 0x3E:
                instr.Opcode = OpCodes.Ble; // <int32 (target)>
                break;

            //Branch to target if less than or equal to.
            case 0x3F:
                instr.Opcode = OpCodes.Blt;// <int32 (target)>
                break;

            //Branch to target if less than.
            case 0x40:
                instr.Opcode = OpCodes.Bne_Un;// <int32 (target)>
                break;

            //Branch to target if unequal or unordered.
            case 0x41:
                instr.Opcode = OpCodes.Bge_Un;// <int32 (target)>
                break;

            //Branch to target if greater than or equal to (unsigned or unordered).
            case 0x42:
                instr.Opcode = OpCodes.Bgt_Un;// <int32 (target)>
                break;

            //Branch to target if greater than (unsigned or unordered).
            case 0x43:
                instr.Opcode = OpCodes.Ble_Un;// <int32 (target)>
                break;

            //Branch to target if less than or equal to (unsigned or unordered).
            case 0x44:
                instr.Opcode = OpCodes.Blt_Un;// <int32 (target)>
                break;

            //Branch to target if less than (unsigned or unordered).
            case 0x45:
                instr.Opcode = OpCodes.Switch;// <uint32, int32,int32 (t1..tN)>
                break;

            //Jump to one of n values.
            case 0x46: instr.Opcode = OpCodes.Ldind_I1; break; //Indirect load value of type int8 as int32 on the stack.

            case 0x47: instr.Opcode = OpCodes.Ldind_U1; break; //Indirect load value of type unsigned int8 as int32 on the stack

            case 0x48: instr.Opcode = OpCodes.Ldind_I2; break; //Indirect load value of type int16 as int32 on the stack.

            case 0x49: instr.Opcode = OpCodes.Ldind_U2; break; //Indirect load value of type unsigned int16 as int32 on the stack

            case 0x4A: instr.Opcode = OpCodes.Ldind_I4; break; //Indirect load value of type int32 as int32 on the stack.

            case 0x4B: instr.Opcode = OpCodes.Ldind_U4; break;

            //Indirect load value of type unsigned int32 as int32 on the stack
            case 0x4C:
                instr.Opcode = OpCodes.Ldind_I8;
                break;

            //Indirect load value of type int64 as int64 on the stack.
            case 0x4D:

                instr.Opcode = OpCodes.Ldind_I;
                break;

            //Indirect load value of type native int as native int on the stack
            case 0x4E:

                instr.Opcode = OpCodes.Ldind_R4;
                break;

            //Indirect load value of type float32 as F on the stack.
            case 0x4F:

                instr.Opcode = OpCodes.Ldind_R8;
                break;

            //Indirect load value of type float64 as F on the stack.
            case 0x50:

                instr.Opcode = OpCodes.Ldind_Ref;
                break;

            //Indirect load value of type object ref as O on the stack.
            case 0x51:

                instr.Opcode = OpCodes.Stind_Ref;
                break;

            //Store value of type object ref (type O) into memory at address
            case 0x52:

                instr.Opcode = OpCodes.Stind_I1;
                break;

            //Store value of type int8 into memory at address
            case 0x53:

                instr.Opcode = OpCodes.Stind_I2;
                break;

            //Store value of type int16 into memory at address
            case 0x54:

                instr.Opcode = OpCodes.Stind_I4;
                break;

            //Store value of type int32 into memory at address
            case 0x55: instr.Opcode = OpCodes.Stind_I8; break;  // Store value of type int64 into memory at address

            case 0x56:

                instr.Opcode = OpCodes.Stind_R4;
                break;

            //Store value of type float32 into memory at address
            case 0x57:

                instr.Opcode = OpCodes.Stind_R8;
                break;

            //Store value of type float64 into memory at address
            case 0x58:

                instr.Opcode = OpCodes.Add;
                break;

            //Add two values, returning a new value.
            case 0x59:

                instr.Opcode = OpCodes.Sub;
                break;

            //Subtract value2 from value1, returning a new value.
            case 0x5A: instr.Opcode = OpCodes.Mul; break;    //Multiply values.

            case 0x5B: instr.Opcode = OpCodes.Div; break;    //Divide two values to return a quotient or floating-point result.

            case 0x5C: instr.Opcode = OpCodes.Div_Un; break; //Divide two values, unsigned, returning a quotient.

            case 0x5D: instr.Opcode = OpCodes.Rem; break;    //Remainder when dividing one value by another.

            case 0x5E:

                instr.Opcode = OpCodes.Rem_Un;
                break;

            //Remainder when dividing one unsigned value by another.
            case 0x5F:
                instr.Opcode = OpCodes.And;
                break;

            //Bitwise AND of two integral values, returns an integral value.
            case 0x60:

                instr.Opcode = OpCodes.Or;
                break;

            //Bitwise OR of two integer values, returns an integer.
            case 0x61:

                instr.Opcode = OpCodes.Xor;
                break;

            //Bitwise XOR of integer values, returns an integer.
            case 0x62:

                instr.Opcode = OpCodes.Shl;
                break;

            //Shift an integer left (shifting in zeros), return an integer.
            case 0x63: instr.Opcode = OpCodes.Shr; break;     //Shift an integer right (shift in sign), return an integer.

            case 0x64: instr.Opcode = OpCodes.Shr_Un; break;  //Shift an integer right (shift in zero), return an integer.

            case 0x65: instr.Opcode = OpCodes.Neg; break;     //Negate value.

            case 0x66: instr.Opcode = OpCodes.Not; break;     //Bitwise complement (logical not).

            case 0x67: instr.Opcode = OpCodes.Conv_I1; break; //Convert to int8, pushing int32 on stack.

            case 0x68: instr.Opcode = OpCodes.Conv_I2; break; //Convert to int16, pushing int32 on stack.

            case 0x69: instr.Opcode = OpCodes.Conv_I4; break; //Convert to int32, pushing int32 on stack.

            case 0x6A: instr.Opcode = OpCodes.Conv_I8; break; //Convert to int64, pushing int64 on stack.

            case 0x6B: instr.Opcode = OpCodes.Conv_R4; break; //Convert to float32, pushing F on stack.

            case 0x6C: instr.Opcode = OpCodes.Conv_R8; break; //Convert to float64, pushing F on stack.

            case 0x6D: instr.Opcode = OpCodes.Conv_U4; break; //Convert to unsigned int32, pushing int32 on stack.

            case 0x6E: instr.Opcode = OpCodes.Conv_U8; break; //Convert to unsigned int64, pushing int64 on stack.

            case 0x6F: instr.Opcode = OpCodes.Callvirt;       // <method>
                break;

            //Call a method associated with an object. Object model instruction
            case 0x70: instr.Opcode = OpCodes.Cpobj; // <typeTok>
                break;

            //Copy a value type from src to dest. Object model instruction
            case 0x71:
                instr.Opcode = OpCodes.Ldobj;// <typeTok>
                break;

            //Copy the value stored at address src to the stack. Object model instruction
            case 0x72:

                instr.Opcode = OpCodes.Ldstr;// <string>
                break;

            //Push a string object for the literal string. Object model instruction
            case 0x73:

                instr.Opcode = OpCodes.Newobj;// <ctor>
                break;

            //Allocate an uninitialized object or value type and call ctor. Object model instruction
            case 0x74:

                instr.Opcode = OpCodes.Castclass; // <class>
                break;

            //Cast obj to class. Object model instruction
            case 0x75:

                instr.Opcode = OpCodes.Isinst; //<class>
                break;

            //Test if obj is an instance of class, returning null or an instance of that class or interface. Object model instruction
            case 0x76: instr.Opcode = OpCodes.Conv_R_Un; break; //Convert unsigned integer to floating-point, pushing F on stack.

            case 0x79: instr.Opcode = OpCodes.Unbox;            //<valuetype>
                break;                                          //Extract a value-type from obj, its boxed representation. Object model instruction

            case 0x7A:
                instr.Opcode = OpCodes.Throw;
                break;

            //Throw an exception. Object model instruction
            case 0x7B:
                instr.Opcode = OpCodes.Ldfld; // <field>
                break;

            //Push the value of field of object (or value type) obj, onto the stack. Object model instruction
            case 0x7C:
                instr.Opcode = OpCodes.Ldflda; // <field>
                break;

            //Push the address of field of object obj on the stack. Object model instruction
            case 0x7D:
                instr.Opcode = OpCodes.Stfld;  //<field>
                break;

            //Replace the value of field of the object obj with value. Object model instruction
            case 0x7E:
                instr.Opcode = OpCodes.Ldsfld;// <field>
                break;

            //Push the value of field on the stack. Object model instruction
            case 0x7F:
                instr.Opcode = OpCodes.Ldsflda;// <field>
                break;

            //Push the address of the static field, field, on the stack. Object model instruction
            case 0x80:
                instr.Opcode = OpCodes.Stsfld; // <field>
                break;

            //Replace the value of field with val. Object model instruction
            case 0x81:
                instr.Opcode = OpCodes.Stobj; //<typeTok>
                break;

            //Store a value of type typeTok at an address. Object model instruction
            case 0x82: instr.Opcode = OpCodes.Conv_Ovf_I1_Un; break;  //Convert unsigned to an int8 (on the stack as int32) and throw an exception on overflow.

            case 0x83:
                instr.Opcode = OpCodes.Conv_Ovf_I2_Un;
                break;

            //Convert unsigned to an int16 (on the stack as int32) and throw an exception on overflow.
            case 0x84: instr.Opcode = OpCodes.Conv_Ovf_I4_Un; break; //Convert unsigned to an int32 (on the stack as int32) and throw an exception on overflow.

            case 0x85: instr.Opcode = OpCodes.Conv_Ovf_I8_Un; break; //Convert unsigned to an int64 (on the stack as int64) and throw an exception on overflow.

            case 0x86: instr.Opcode = OpCodes.Conv_Ovf_U1_Un; break; //Convert unsigned to an unsigned int8 (on the stack as int32) and throw an exception on overflow.

            case 0x87:

                instr.Opcode = OpCodes.Conv_Ovf_I2_Un;
                break;

            //Convert unsigned to an unsigned int16 (on the stack as int32) and throw an exception on overflow.
            case 0x88:

                instr.Opcode = OpCodes.Conv_Ovf_U4_Un;
                break;

            //Convert unsigned to an unsigned int32 (on the stack as int32) and throw an exception on overflow.
            case 0x89:

                instr.Opcode = OpCodes.Conv_Ovf_U8_Un;
                break;

            //Convert unsigned to an unsigned int64 (on the stack as int64) and throw an exception on overflow.
            case 0x8A:

                instr.Opcode = OpCodes.Conv_Ovf_I_Un;
                break;

            //Convert unsigned to a native int (on the stack as native int) and throw an exception on overflow.
            case 0x8B:

                instr.Opcode = OpCodes.Conv_Ovf_U_Un;
                break;

            //Convert unsigned to a native unsigned int (on the stack as native int) and throw an exception on overflow.
            case 0x8C:

                instr.Opcode = OpCodes.Box;// <typeTok>
                break;

            //Convert a boxable value to its boxed form Object model instruction
            case 0x8D:

                instr.Opcode = OpCodes.Newarr;// <etype>
                break;

            //Create a new array with elements of type etype. Object model instruction
            case 0x8E:

                instr.Opcode = OpCodes.Ldlen;
                break;

            //Push the length (of type native unsigned int) of array on the stack. Object model instruction
            case 0x8F:

                instr.Opcode = OpCodes.Ldelema;// <class>
                break;

            //Load the address of element at index onto the top of the stack. Object model instruction
            case 0x90:

                instr.Opcode = OpCodes.Ldelem_I1;
                break;

            //Load the element with type int8 at index onto the top of the stack as an int32. Object model instruction
            case 0x91:

                instr.Opcode = OpCodes.Ldelem_U1;
                break;

            //Load the element with type unsigned int8 at index onto the top of the stack as an int32. Object model instruction
            case 0x92:

                instr.Opcode = OpCodes.Ldelem_I2;
                break;

            //Load the element with type int16 at index onto the top of the stack as an int32. Object model instruction
            case 0x93:

                instr.Opcode = OpCodes.Ldelem_U2;
                break;

            //Load the element with type unsigned int16 at index onto the top of the stack as an int32. Object model instruction
            case 0x94:

                instr.Opcode = OpCodes.Ldelem_I4;
                break;

            //Load the element with type int32 at index onto the top of the stack as an int32. Object model instruction
            case 0x95:

                instr.Opcode = OpCodes.Ldelem_U4;
                break;

            //Load the element with type unsigned int32 at index onto the top of the stack as an int32. Object model instruction
            case 0x96:

                instr.Opcode = OpCodes.Ldelem_I8;
                break;

            //Load the element with type unsigned int64 at index onto the top of the stack as an int64 (alias for ldelem.i8). Object model instruction
            case 0x97:

                instr.Opcode = OpCodes.Ldelem_I;
                break;

            //Load the element with type native int at index onto the top of the stack as a native int. Object model instruction
            case 0x98:

                instr.Opcode = OpCodes.Ldelem_R4;
                break;

            //Load the element with type float32 at index onto the top of the stack as an F Object model instruction
            case 0x99:

                instr.Opcode = OpCodes.Ldelem_R8;
                break;

            //Load the element with type float64 at index onto the top of the stack as an F. Object model instruction
            case 0x9A:

                instr.Opcode = OpCodes.Ldelem_Ref;
                break;

            //Load the element at index onto the top of the stack as an O. The type of the O is the same as the element type of the array pushed on the CIL stack. Object model instruction
            case 0x9B:

                instr.Opcode = OpCodes.Stelem_I;
                break;

            //Replace array element at index with the i value on the stack. Object model instruction
            case 0x9C:

                instr.Opcode = OpCodes.Stelem_I1;
                break;

            //Replace array element at index with the int8 value on the stack. Object model instruction
            case 0x9D:

                instr.Opcode = OpCodes.Stelem_I2;
                break;

            //Replace array element at index with the int16 value on the stack. Object model instruction
            case 0x9E:

                instr.Opcode = OpCodes.Stelem_I4;
                break;

            //Replace array element at index with the int32 value on the stack. Object model instruction
            case 0x9F: instr.Opcode = OpCodes.Stelem_I8; break;  //Replace array element at index with the int64 value on the stack. Object model instruction

            case 0xA0: instr.Opcode = OpCodes.Stelem_R4; break;  //Replace array element at index with the float32 value on the stack. Object model instruction

            case 0xA1: instr.Opcode = OpCodes.Stelem_R8; break;  //Replace array element at index with the float64 value on the stack. Object model instruction

            case 0xA2: instr.Opcode = OpCodes.Stelem_Ref; break; //Replace array element at index with the ref value on the stack. Object model instruction

            case 0xA3:
                instr.Opcode = OpCodes.Ldelem;// <typeTok>
                break;

            //Load the element at index onto the top of the stack. Object model instruction
            case 0xA4:
                instr.Opcode = OpCodes.Stelem;// <typeTok>
                break;

            //Replace array element at index with the value on the stack Object model instruction
            case 0xA5: instr.Opcode = OpCodes.Unbox_Any;//<typeTok>
                break;

            //Extract a value-type from obj, its boxed representation Object model instruction
            case 0xB3: instr.Opcode = OpCodes.Conv_Ovf_I1; break;

            //Convert to an int8 (on the stack as int32) and throw an exception on overflow.
            case 0xB4: instr.Opcode = OpCodes.Conv_Ovf_U1; break; //Convert to an unsigned int8 (on the stack as int32) and throw an exception on overflow.

            case 0xB5: instr.Opcode = OpCodes.Conv_Ovf_I2; break; //Convert to an int16 (on the stack as int32) and throw an exception on overflow.

            case 0xB6: instr.Opcode = OpCodes.Conv_Ovf_U2; break; //Convert to an unsigned int16 (on the stack as int32) and throw an exception on overflow.

            case 0xB7: instr.Opcode = OpCodes.Conv_Ovf_I4; break; //Convert to an int32 (on the stack as int32) and throw an exception on overflow.

            case 0xB8: instr.Opcode = OpCodes.Conv_Ovf_U4; break; //Convert to an unsigned int32 (on the stack as int32) and throw an exception on overflow.

            case 0xB9: instr.Opcode = OpCodes.Conv_Ovf_I8; break; //Convert to an int64 (on the stack as int64) and throw an exception on overflow.

            case 0xBA: instr.Opcode = OpCodes.Conv_Ovf_U8; break; //Convert to an unsigned int64 (on the stack as int64) and throw an exception on overflow.

            case 0xC2:
                instr.Opcode = OpCodes.Refanyval;// <type>
                break;

            //Push the address stored in a typed reference. Object model instruction
            case 0xC3:
                instr.Opcode = OpCodes.Ckfinite;
                break;

            //Throw ArithmeticException if value is not a finite number.
            case 0xC6:
                instr.Opcode = OpCodes.Mkrefany; // <class>
                break;

            //Push a typed reference to ptr of type class onto the stack. Object model instruction
            case 0xD0:
                instr.Opcode = OpCodes.Ldtoken;// <token>
                break;

            //Convert metadata token to its runtime representation. Object model instruction
            case 0xD1: instr.Opcode = OpCodes.Conv_U2; break;    // Convert to unsigned int16, pushing int32 on stack.

            case 0xD2: instr.Opcode = OpCodes.Conv_U1; break;    // Convert to unsigned int8, pushing int32 on stack.

            case 0xD3: instr.Opcode = OpCodes.Conv_I;  break;    // Convert to native int, pushing native int on stack.

            case 0xD4: instr.Opcode = OpCodes.Conv_Ovf_I; break; // Convert to a native int (on the stack as native int) and throw an exception on overflow.

            case 0xD5: instr.Opcode = OpCodes.Conv_Ovf_U; break; // Convert to a native unsigned int (on the stack as native int) and throw an exception on overflow.

            case 0xD6: instr.Opcode = OpCodes.Add_Ovf; break;    // Add signed integer values with overflow check.

            case 0xD7: instr.Opcode = OpCodes.Add_Ovf_Un; break; // Add unsigned integer values with overflow check.

            case 0xD8:
                instr.Opcode = OpCodes.Mul_Ovf;
                break;

            // Multiply signed integer values. Signed result shall fit in same size
            case 0xD9:
                instr.Opcode = OpCodes.Mul_Ovf_Un;
                break;

            // Multiply unsigned integer values. Unsigned result shall fit in same size
            case 0xDA:
                instr.Opcode = OpCodes.Sub_Ovf;
                break;

            // Subtract native int from a native int. Signed result shall fit in same size
            case 0xDB:
                instr.Opcode = OpCodes.Sub_Ovf_Un;
                break;

            // Subtract native unsigned int from a native unsigned int. Unsigned result shall fit in same size.
            case 0xDC:
                instr.Opcode = OpCodes.Endfinally;
                break;

            // End finally clause of an exception block.
            case 0xDD:
                instr.Opcode = OpCodes.Leave;   // <int32 (target)>
                break;

            //Exit a protected region of code.
            case 0xDE:
                instr.Opcode = OpCodes.Leave_S; // <int8 (target)>
                break;

            //Exit a protected region of code, short form.
            case 0xDF:
                instr.Opcode = OpCodes.Stind_I;
                break;

            // Store value of type native int into memory at address
            case 0xE0:
                instr.Opcode = OpCodes.Conv_U;
                break;

            //Convert to native unsigned int, pushing native int on stack.
            case 0xFE:
                switch (rdr.ReadByte())
                {
                case 0x00: instr.Opcode = OpCodes.Arglist; break;       // Return argument list handle for the current method.

                case 0x01: instr.Opcode = OpCodes.Ceq; break;           // Push 1 (of type int32) if value1 equals value2, else push 0.

                case 0x02:
                    instr.Opcode = OpCodes.Cgt;
                    break;

                // Push 1 (of type int32) if value1 > value2, else push 0.
                case 0x03:
                    instr.Opcode = OpCodes.Cgt_Un;
                    break;

                // Push 1 (of type int32) if value1 > value2, unsigned or unordered, else push 0.
                case 0x04:
                    instr.Opcode = OpCodes.Clt;
                    break;

                // Push 1 (of type int32) if value1 < value2, else push 0.
                case 0x05:
                    instr.Opcode = OpCodes.Clt_Un;
                    break;

                // Push 1 (of type int32) if value1 < value2, unsigned or unordered, else push 0.
                case 0x06:
                    instr.Opcode = OpCodes.Ldftn;// <method>
                    break;

                // Push a pointer to a method referenced by method, on the stack.
                case 0x07:
                    instr.Opcode = OpCodes.Ldvirtftn;// <method>
                    break;

                // Push address of virtual method on the stack. Object model instruction
                case 0x09:
                    instr.Opcode = OpCodes.Ldarg;//<uint16 (num)>
                    break;

                //Load argument numbered num onto the stack.
                case 0x0A:
                    instr.Opcode = OpCodes.Ldarga;// <uint16 (argNum)>
                    break;

                //Fetch the address of argument argNum.
                case 0x0B:
                    instr.Opcode = OpCodes.Starg; // <uint16 (num)>
                    break;

                //Store value to the argument numbered num.
                case 0x0C:
                    instr.Opcode = OpCodes.Ldloc; //<uint16 (indx)>
                    break;

                //Load local variable of index indx onto stack.
                case 0x0D: instr.Opcode = OpCodes.Ldloca; //<uint16 (indx)>
                    break;

                //Load address of local variable with index indx.
                case 0x0E: instr.Opcode = OpCodes.Stloc; // <uint16 (indx)>
                    break;

                // Pop a value from stack into local variable indx.
                case 0x0F:
                    instr.Opcode = OpCodes.Localloc;
                    break;

                // Allocate space from the local memory pool.
                case 0x11:
                    instr.Opcode = OpCodes.Endfilter;
                    break;

                // End an exception handling filter clause.
                case 0x12:
                    instr.Opcode = OpCodes.Unaligned;   //. (alignment)
                    break;

                //Subsequent pointer instruction might be unaligned. Prefix to instruction
                case 0x13:
                    instr.Opcode = OpCodes.Volatile;
                    break;

                //Subsequent pointer reference is volatile. Prefix to instruction
                case 0x14: instr.Opcode = OpCodes.Tailcall; break; // Subsequent call terminates current method Prefix to instruction

                case 0x15:
                    instr.Opcode = OpCodes.Initobj; // <typeTok>
                    break;

                // Initialize the value at address dest. Object model instruction
                case 0x16:
                    instr.Opcode = OpCodes.Constrained; //. <thisType>
                    break;

                // Call a virtual method on a type constrained to be type T Prefix to instruction
                case 0x17:
                    instr.Opcode = OpCodes.Cpblk;
                    break;

                // Copy data from memory to memory.
                case 0x18:
                    instr.Opcode = OpCodes.Initblk;
                    break;

                //Set all bytes in a block of memory to a given byte value.
                case 0x19:

                    throw new NotImplementedException();

                //instr.Opcode = OpCodes.no {
                //break;
                //typecheck,
                //rangecheck,
                //nullcheck
                //The specified fault check(s) normally performed as part of the execution of the subsequent instruction can/shall be skipped. Prefix to instruction
                case 0x1A:
                    instr.Opcode = OpCodes.Rethrow;
                    break;

                // Rethrow the current exception. Object model instruction
                case 0x1C:
                    instr.Opcode = OpCodes.Sizeof; //<typeTok>
                    break;

                //Push the size, in bytes, of a type as an unsigned int32. Object model instruction
                case 0x1D:
                    instr.Opcode = OpCodes.Refanytype;
                    break;

                //Push the type token stored in a typed reference. Object model instruction
                case 0x1E:
                    instr.Opcode = OpCodes.Readonly;
                    break;
                    //Specify that the subsequent array address operation performs no type check at runtime, and that it returns a controlled-mutability managed pointer Prefix to instruction
                }
                break;
                #endregion
            }
            instr.Length = (int)(rdr.Address - addr);
            return(instr);
        }