// returns target, source and jump for current command
        private int TSJ(int Command, out Register Target, out Register Source, out int IPJump)
        {
            Target = null;
              Source = null;
              IPJump = 1;

              int TargetType = Command & TT, SourceType = Command & ST, Executable = GetExecutable(Command);

              int TargetValue = Code[IP + 1]; // target is always first argument
              switch (Executable) // fill the target
              {
            case ADD:
            case SUB:
            case MUL:
            case DIV:
            case MOD:
            case XOR:
            case MOV:
            case NOT:
            case LE:
            case EQ:
            case IAR:
            case IARND:
            case CHI:
            case RET:
            case LNK:
            case GTI:
            case JF:
            case JMP:
            case JFL:
            case JMPL:
            case JT:
            case JTL:
            case GCRC:
            case GTC:
            case AESC:
            case AESD:
            case GDAT:
            case EQAR:
              switch (TargetType)
              {
            case TR: Target = Registers[TargetValue]; break; // register
            case TV: Target = new Register(this, TargetValue); break; // value (create temp register for manIPulations)
              }
              break;
              }

              switch (Executable) // fill the source
              {
            case ADD:
            case SUB:
            case MUL:
            case DIV:
            case MOD:
            case XOR:
            case MOV:
            case LE:
            case EQ:
            case CHI:
            case LNK:
            case GTI:
            case GTC:
            case GCRC:
            case AESC:
            case AESD:
            case EQAR:
              int SourceValue = Code[IP + (Executable != CHI ? 2 : 3)];
              switch (SourceType) // source is..
              {
            case SR: Source = Registers[SourceValue]; break; // register
            case SV: Source = new Register(this, SourceValue); break; // value (create temp register for manipulations)
              }
              break;
            case IAR: case IARND:
              switch (SourceType) // source is..
              {
            case SR: Source = new Register(this, RegisterType.Link); break; // register
            case SV: Source = new Register(this, RegisterType.Value); break; // value
              }
              break;
              }

              switch (Executable) // fill the ip jump
              {
            case RET:
            case NOT:
            case GDAT:
              IPJump = 2; break;
            case ADD:
            case SUB:
            case MUL:
            case DIV:
            case MOD:
            case XOR:
            case MOV:
            case LE:
            case EQ:
            case LNK:
            case GTI:
            case GTC:
            case EQAR:
              IPJump = 3; break;
            case IAR:
              IPJump = 4 + Code[IP + 3]; break;
            case CHI:
            case CRE:
            case AESC:
            case AESD:
              IPJump = 4; break;
            case JF:
            case JMP:
            case JFL:
            case JMPL:
            case JT:
            case JTL:
              IPJump = 2; break;
            case IARND:
            case GCRC:
              IPJump = 5; break;
              }

              return Executable;
        }
 private void MakeCipherDecipher(int Executable, Register Target, Register Source, Register Key)
 {
     if (Target == null || Source == null || Key == null)
     throw new Exception("One of the registers is nullable");
       if (Target.Type != RegisterType.Array || Source.Type != RegisterType.Array || Key.Type != RegisterType.Array)
     throw new Exception("One of the registers has invalid type");
       byte[] KeyBytes = Cvt.ToByteArray(Key.Value as Int32[]);
       byte[] SourceBytes = Cvt.ToByteArray(Source.Value as Int32[]);
       var csp = GetAESCSP(KeyBytes);
       var transform = Executable == AESC ? csp.CreateEncryptor() : csp.CreateDecryptor();
       byte[] TargetBytes = transform.TransformFinalBlock(SourceBytes, 0, SourceBytes.Length);
       Target.InitArray(0, Cvt.ToIntArray(TargetBytes));
 }
 /// <summary>source xor target</summary>
 internal void Xor(Register source)
 {
     switch (Type)
       {
     case RegisterType.Value: IntValue ^= source.FinalValue; break;
     case RegisterType.Link: LinkedRegisterValue.Xor(source); break;
     case RegisterType.Array: ArrayValue[ArrayIndex] ^= source.FinalValue; break;
       }
 }
        public object Run()
        {
            Analyze(); // формируем список меток
              CheckCode();
              IP = 0;
              while (IP >= 0 && IP < Code.Length)
              {
            int Command = Code[IP];

            Register Target = null, Source = null;
            int Jump = 1;

            Int32 Index, Count, CodeValue, Type, Param1;
            Int32[] Values; // for arrays

            int Executable = TSJ(Command, out Target, out Source, out Jump);
            switch (Executable) // исполяемая команда
            {
              case CRE:
            Index = Code[IP + 1];
            Type = Code[IP + 2];
            Param1 = Code[IP + 3];
            switch (Type)
            {
              case 0:
                Registers[Index] = new Register(this, Param1);
                break;
              case 1:
                Registers[Index] = new Register(this, RegisterType.Array);
                Registers[Index].CreateArray(Param1);
                break;
              case 2:
                Registers[Index] = new Register(this, RegisterType.Link);
                if (Param1 > 0)
                  Registers[Index].InitLink(Registers[Param1]);
                break;
              default: throw new Exception("Invalid type");
            }
            break;
              case RET:
            return Target.Value;
              case ADD:
            Target.Add(Source);
            break;
              case SUB:
            Target.Sub(Source);
            break;
              case MUL:
            Target.Mul(Source);
            break;
              case DIV:
            Target.Div(Source);
            break;
              case MOD:
            Target.Mod(Source);
            break;
              case XOR:
            Target.Xor(Source);
            break;
              case MOV:
            Target.FinalValue = Source.FinalValue;
            break;
              case NOT:
            Target.FinalValue = ~Target.FinalValue;
            break;
              case LE:
            Flag = Target.FinalValue < Source.FinalValue;
            break;
              case EQ:
            Flag = Target.FinalValue == Source.FinalValue;
            break;
              case IAR:
            Index = Code[IP + 2];
            Count = Code[IP + 3];
            Values = new Int32[Count];
            for (int i = 0; i < Count; i++)
            {
              CodeValue = Code[IP + 4 + i];
              Values[i] = Source.Type == RegisterType.Value ? CodeValue : Registers[CodeValue].FinalValue;
            }
            Target.InitArray(Index, Values);
            break;
              case IARND:
            Index = Code[IP + 2];
            Count = Code[IP + 3];
            CodeValue = Code[IP + 4];
            int Seed = Source.Type == RegisterType.Value ? CodeValue : Registers[CodeValue].FinalValue;
            Random Rnd = new Random(Seed);
            Values = new Int32[Count];
            for (int i = 0; i < Count; i++)
              Values[i] = Rnd.Next();
            Target.InitArray(Index, Values);
            break;
              case EQAR:
            if (Target.Type == RegisterType.Array && Source.Type == RegisterType.Array)
            {
              int TargetCount = Target.GetArrayCount(), SourceCount = Source.GetArrayCount();
              if (TargetCount == SourceCount)
              {
                Int32[] TargetArray = (Target.Value as Int32[]), SourceArray = (Source.Value as Int32[]);
                bool IsEqual = true;
                for (int i = 0; i < TargetCount; i++)
                {
                  IsEqual = TargetArray[i] == SourceArray[i];
                  if (!IsEqual) break;
                }
                Flag = IsEqual;
              }
              else
                Flag = false;
            }
            else
              Flag = false;
            break;
              case CHI:
            Target.ChangeArrayIndex(Code[IP + 2], Source.FinalValue);
            break;
              case LNK:
            Target.InitLink(Source);
            break;
              case GTI:
            Target.FinalValue = Source.GetArrayIndex();
            break;
              case GTC:
            Target.FinalValue = Source.GetArrayCount();
            break;
              case GCRC:
            if (Source.Type != RegisterType.Array) throw new Exception("Invalid source type");
            Index = Code[IP + 3];
            Count = Code[IP + 4];
            if (Index < 0) Index = 0;
            if (Count == 0) Count = Source.GetArrayCount();
            Values = Source.Value as Int32[];
            Int32[] intsForCRC = new Int32[Count];
            Array.Copy(Values, Index, intsForCRC, 0, Count);
            byte[] bytesForCRC = Cvt.ToByteArray(intsForCRC);
            Target.FinalValue = (int)CheckSum.CalcCRC32(bytesForCRC);
            break;
              case AESC:
              case AESD:
            MakeCipherDecipher(Executable, Target, Source, Registers[Code[IP + 3]]);
            break;
              case GDAT:
            Target.FinalValue = Cvt.DateToInteger(DateTime.Now);
            break;
              // jumps
              case JMP:
            Jump = Target.FinalValue;
            break;
              case JF:
            Jump = 0;
            if (!Flag) IP += Target.FinalValue; else IP += 2;
            break;
              case JT:
            Jump = 0;
            if (Flag) IP += Target.FinalValue; else IP += 2;
            break;
              case JMPL:
            Jump = 0;
            IP = Labels[Target.FinalValue];
            break;
              case JFL:
            Jump = 0;
            if (!Flag) IP = Labels[Target.FinalValue]; else IP += 2;
            break;
              case JTL:
            Jump = 0;
            if (Flag) IP = Labels[Target.FinalValue]; else IP += 2;
            break;
              default:
            Jump = 1;
            break;
            }
            IP += Jump;
              }
              return -1;
        }
 public void InitLink(Register Link)
 {
     Type = RegisterType.Link;
       LinkedRegisterValue = Link;
 }