// Scan the object code to find the first argument to ProtoMember for a given CAG
        private static int getProtoMemberArgument(CustomAttributeData att, long protoMemberCtor)
        {
            // Disassemble the CAG
            var code     = asm.Disassemble(att.GetMethodBody(), (long)att.VirtualAddress.Start);
            var insIndex = -1;
            var disp     = 0;

            // Step forwards through each instruction
            while (++insIndex < code.Length && disp == 0)
            {
                var ins = code[insIndex];

                // Look for JMP and CALL instructions to the ProtoMember constructor
                if ((ins.Id == X86InstructionId.X86_INS_JMP || ins.Id == X86InstructionId.X86_INS_CALL) &&
                    ins.Details.Operands[0].Immediate == protoMemberCtor)
                {
                    // Now step backwards looking for the most recent LEA EDX instruction
                    while (--insIndex >= 0 && disp == 0)
                    {
                        ins = code[insIndex];

                        if (ins.Id == X86InstructionId.X86_INS_LEA &&
                            ins.Details.ExplicitlyWrittenRegisters[0].Id == X86RegisterId.X86_REG_EDX)
                        {
                            // The instruction is LEA EDX, [R8 + disp]
                            // We know that R8 is zero so the displacement is the field number
                            disp = (int)ins.Details.Displacement;
                        }
                    }
                    if (insIndex == -1)
                    {
                        throw new InvalidOperationException("Unable to determine ProtoMember field number");
                    }
                }
            }
            return(disp);
        }