public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
        {
            var xAssembler        = aAssembler;
            var xMethodInfo       = (MethodInfo)aMethodInfo;
            var xMethodBaseAsInfo = xMethodInfo.MethodBase as global::System.Reflection.MethodInfo;

            if (xMethodBaseAsInfo.ReturnType != typeof(void))
            {
                throw new Exception("Events with return type not yet supported!");
            }

            /*
             * EAX contains the GetInvocationList() array at the index at which it was last used
             * EDX contains the index at which the EAX is
             * EBX contains the number of items in the array
             * ECX contains the argument size
             */

            XS.ClearInterruptFlag();

            XS.Comment("Get Invoke list count");
            var xGetInvocationListMethod = typeof(MulticastDelegate).GetMethod("GetInvocationList");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Call(LabelName.Get(xGetInvocationListMethod));
            XS.Add(ESP, 4);
            XS.Pop(EAX);
            XS.Add(EAX, 8);
            XS.Set(EBX, EAX, sourceIsIndirect: true);

            XS.Comment("Get invoke method");
            XS.Add(EAX, 8);
            XS.Set(EDI, EAX, sourceIsIndirect: true, sourceDisplacement: 4);

            XS.Comment("Get ArgSize");
            int xArgSizeOffset = Ldfld.GetFieldOffset(typeof(global::System.Delegate), "$$ArgSize$$");

            Ldarg.DoExecute(aAssembler, xMethodInfo, 0);
            XS.Add(ESP, 4);
            XS.Pop(ECX);
            XS.Add(ECX, (uint)xArgSizeOffset);
            XS.Set(ECX, ECX, sourceIsIndirect: true);

            XS.Comment("Set current invoke list index");
            XS.Set(EDX, 0);

            XS.Label(".BEGIN_OF_LOOP");
            {
                XS.Compare(EDX, EBX);
                XS.Jump(Assembler.x86.ConditionalTestEnum.GreaterThanOrEqualTo, ".END_OF_INVOKE");

                XS.PushAllRegisters();

                XS.Comment("Check if delegate has $this");
                XS.Set(EDI, EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
                XS.Add(EDI, 4);
                XS.Set(EDI, EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.Object System.Delegate._target"));
                XS.Compare(EDI, 0);
                XS.Jump(Assembler.x86.ConditionalTestEnum.Zero, ".NO_THIS");
                XS.Label(".HAS_THIS");
                XS.Push(EDI);
                XS.Push(0);
                XS.Label(".NO_THIS");
                XS.Set(EDI, EAX, sourceIsIndirect: true, sourceDisplacement: 4);
                XS.Set(EDI, EDI, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "System.IntPtr System.Delegate._methodPtr"));

                XS.Comment("Check if delegate has args");
                XS.Compare(ECX, 0);
                XS.Jump(Assembler.x86.ConditionalTestEnum.Zero, ".NO_ARGS");
                XS.Label(".HAS_ARGS");
                XS.Sub(ESP, ECX);
                XS.Push(EDI);
                XS.Set(EDI, ESP);
                XS.Add(EDI, 4);
                XS.Set(ESI, EBP);
                XS.Add(ESI, 8);
                new Assembler.x86.Movs {
                    Size = 8, Prefixes = Assembler.x86.InstructionPrefixes.Repeat
                };
                XS.Pop(EDI);
                XS.Label(".NO_ARGS");
                XS.Call(EDI);

                XS.PopAllRegisters();
                XS.Increment(EDX);
                XS.Jump(".BEGIN_OF_LOOP");
            }

            XS.Label(".END_OF_INVOKE");
            XS.Set(EDX, EBP, sourceDisplacement: Ldarg.GetArgumentDisplacement(xMethodInfo, 0));
            XS.Set(EDX, EDX, sourceDisplacement: Ldfld.GetFieldOffset(xMethodInfo.MethodBase.DeclaringType, "$$ReturnsValue$$"));
            XS.Compare(EDX, 0);
            XS.Jump(Assembler.x86.ConditionalTestEnum.Equal, ".NO_RETURN");

            XS.Label(".HAS_RETURN");
            XS.Exchange(EBP, EDX, destinationDisplacement: 8);
            XS.Exchange(EBP, EDX, destinationDisplacement: 4);
            XS.Exchange(EBP, EDX, destinationIsIndirect: true);
            XS.Push(EDX);
            XS.Set(ESP, EDI, destinationDisplacement: 12);

            XS.Label(".NO_RETURN");
            XS.EnableInterrupts();
        }
Beispiel #2
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4)));
            uint xStackSize = aElementSize;

            if (xStackSize % 4 != 0)
            {
                xStackSize += 4 - xStackSize % 4;
            }
            // Do index out of range check
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException";
            var xIndexOutOfRangeExeptionLabel   = xBaseLabel + "_IndexOutOfRangeException";

            XS.Push(ESP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n  => _, array, 0, index, value * n, array
            XS.Push(0);                                          // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0
            Ldlen.Assemble(aAssembler, debugEnabled, false);     // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length
            XS.Pop(EAX);                                         //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n
            XS.Compare(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize);
            XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel);

            XS.Compare(EAX, 0);
            XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel);

            XS.Label(xIndexOutOfRangeExeptionLabel);
            XS.Exchange(BX, BX);
            Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled);

            XS.Label(xNoIndexOutOfRangeExeptionLabel);

            // calculate element offset into array memory (including header)
            XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index
            XS.Set(EDX, aElementSize);
            XS.Multiply(EDX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4);

            XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array
            XS.Add(EDX, EAX);
            XS.Push(EDX);

            XS.Pop(ECX);

            //get bytes
            var bytes = aElementSize / 4;

            for (uint i = bytes; i > 0; i -= 1)
            {
                new Comment(aAssembler, "Start 1 dword");
                XS.Pop(EBX);
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                XS.Add(ECX, 4);
            }
            switch (aElementSize % 4)
            {
            case 1:
            {
                new Comment(aAssembler, "Start 1 byte");
                XS.Pop(EBX);
                XS.Set(ECX, BL, destinationIsIndirect: true);
                break;
            }

            case 2:
            {
                new Comment(aAssembler, "Start 1 word");
                XS.Pop(EBX);
                XS.Set(ECX, BX, destinationIsIndirect: true);
                break;
            }

            case 3:
            {
                new Comment(aAssembler, "Start 3 word");
                XS.Pop(EBX);
                XS.And(EBX, 0xFFFFFF);         // Only take the value of the lower three bytes
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!");
            }

            XS.Add(ESP, 12);
        }
Beispiel #3
0
 public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
 {
     XS.Exchange(XSRegisters.BX, XSRegisters.BX);
 }