zl程序教程

您现在的位置是:首页 >  其它

当前栏目

IL合集

合集 IL
2023-06-13 09:14:44 时间

    由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多线程合集,目前IOC方面的困难已经解决掉,就差怎么封装了,有想法的看官可以加QQ群6406277,四川观察就是我,多线程方面的后面demo写出来整理好之后,届时会为大家奉上。,IL合集中注释已经写清楚,不明白可以在群里找我,好了,不多啰嗦,正文开始。

  首先出场的是两数相加用IL实现

     Add

 #region Add
            {
                var methodAdd = typeBulder.DefineMethod("Add", MethodAttributes.Public, typeof(int), new Type[] { typeof(int), typeof(int) });
                var ilMethod = methodAdd.GetILGenerator();
                var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
                ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Add);//将第一个和第二个参数相加,
                ilMethod.Emit(OpCodes.Stloc_0);//结果赋值给第0个本地变量
                ilMethod.Emit(OpCodes.Ldloc_0);//加载倒栈中
                ilMethod.EmitCall(OpCodes.Call, method, new Type[] { typeof(int) });//输出
                ilMethod.Emit(OpCodes.Ldloc_0);//加载
                ilMethod.Emit(OpCodes.Ret);//返回相加后的结果
            }
            #endregion

And

 #region And
            {
                var methodAnd = typeBulder.DefineMethod("And", MethodAttributes.Public, typeof(int), new Type[] { typeof(int), typeof(int) });
                var ilMethod = methodAnd.GetILGenerator();
                var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
                ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上
                ilMethod.Emit(OpCodes.And);//将第一个和第二个参数相加,
                ilMethod.Emit(OpCodes.Stloc_0);//将And结果 赋值给local
                ilMethod.Emit(OpCodes.Ldloc_0);//将Local推到栈
                ilMethod.EmitCall(OpCodes.Call, method, new Type[] { typeof(int) });
                ilMethod.Emit(OpCodes.Ldloc_0);////将Local推到栈
                ilMethod.Emit(OpCodes.Ret);//返回And后的结果
            }
            #endregion

ble bgt bge等比较大小相关的

  #region Beq bgt bge ble blt
            {
                var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
                var methodBeq = typeBulder.DefineMethod("Beq",MethodAttributes.Public,typeof(void),new Type[] { typeof(int),typeof(int)});
                var ilMethod = methodBeq.GetILGenerator();
                var labelEq = ilMethod.DefineLabel();
                var labelNotEq= ilMethod.DefineLabel();
                ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Beq, labelEq);//第一个和第二个是否相等
                ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上
                ilMethod.Emit(OpCodes.Bge, labelNotEq);//第一个是否大于等于第二个  可以自行更换为Bgt,ble blt
                ilMethod.Emit(OpCodes.Ret);
                ilMethod.MarkLabel(labelEq);
                ilMethod.Emit(OpCodes.Ldstr, "第一个数等于第二个数");
                ilMethod.Emit(OpCodes.Call, method);
                ilMethod.Emit(OpCodes.Ret);
                ilMethod.MarkLabel(labelNotEq);
                ilMethod.Emit(OpCodes.Ldstr, "第一个数大于等于第二个数");
                ilMethod.Emit(OpCodes.Call, method);
                ilMethod.Emit(OpCodes.Ret);
            }
            #endregion

 IL构造循环代码

  #region 循环
            {
                var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
                var methodInt = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
                var methodXh = typeBulder.DefineMethod("Xunhuan", MethodAttributes.Public, typeof(void), new Type[] { });
                var ilMethod = methodXh.GetILGenerator();
                var localBegin=ilMethod.DeclareLocal(typeof(int));//定义循环开始变量
                var localEnd= ilMethod.DeclareLocal(typeof(int));//结束变量
                var labelXunhuan = ilMethod.DefineLabel();//定义循环主体
                var labelEnd= ilMethod.DefineLabel();//定义结束标签主体
                var labelBreak = ilMethod.DefineLabel();//定义中断标签
                ilMethod.Emit(OpCodes.Ldc_I4, 0);//将0加载到栈上
                ilMethod.Emit(OpCodes.Stloc_0);//这两句是给第0个局部变量赋值,0
                ilMethod.Emit(OpCodes.Ldc_I4, 5);//将5加载到栈上
                ilMethod.Emit(OpCodes.Stloc, 1);//这两句是给第1个局部变量赋值,5
                ilMethod.Emit(OpCodes.Br, labelXunhuan);//无条件跳转到循环的label,即开始循环
                ilMethod.MarkLabel(labelEnd);//标记这段代码是labelend的代码
                ilMethod.Emit(OpCodes.Ldstr,"循环结束");
                ilMethod.Emit(OpCodes.Call, method);//输出循环结束
                ilMethod.Emit(OpCodes.Ret);//返回
                ilMethod.MarkLabel(labelBreak);
                ilMethod.Emit(OpCodes.Ldstr, "循环终止");
                ilMethod.Emit(OpCodes.Call, method);//输出循环结束
                ilMethod.Emit(OpCodes.Break);
                ilMethod.Emit(OpCodes.Ret);//返回
                ilMethod.MarkLabel(labelXunhuan);//标记是labelbegin的代码
                ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量
                ilMethod.Emit(OpCodes.Ldloc_1);//从栈中加载第1个局部变量
                ilMethod.Emit(OpCodes.Bge, labelEnd);//比较第0个是否小于等于第一个
                ilMethod.Emit(OpCodes.Ldloc_0);//加载循环的第0变量
                ilMethod.Emit(OpCodes.Call, methodInt);//打印出来
                ilMethod.Emit(OpCodes.Ldc_I4,1);//将1加载到栈上
                ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量
                ilMethod.Emit(OpCodes.Add);//相加
                ilMethod.Emit(OpCodes.Stloc, 0);//结果赋值给本地0个局部变量
                ilMethod.Emit(OpCodes.Ldc_I4, 3);
                ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量
                ilMethod.Emit(OpCodes.Beq, labelBreak);//比较第0个是否小于等于第一个
                ilMethod.Emit(OpCodes.Br, labelXunhuan);
               
            }

            #endregion

IL构建对象

    #region NewObj创建对象
            {
                var conTest = typeof(TestNewobj).GetConstructors().FirstOrDefault(s => s.GetParameters().Length > 0);
                DynamicMethod dynamicMethod = new DynamicMethod("CreateInstance", typeof(TestNewobj), new Type[] { typeof(int), typeof(int) });//创建一个动态方法,方法名称,返回值,入参
                var il = dynamicMethod.GetILGenerator();
                il.Emit(OpCodes.Nop);//不做操作
                il.Emit(OpCodes.Ldarg_0);//从堆栈加载出方法的第0索引参数
                il.Emit(OpCodes.Ldarg_1);//1索引参数
                il.Emit(OpCodes.Newobj,conTest);//调用构造方法,并传入0,1索引参数的值
                il.Emit(OpCodes.Ret);//返回创建的对象
               var objCreator = dynamicMethod.CreateDelegate(typeof(Func<int,int, TestNewobj>)) as Func<int,int, TestNewobj>;
                var result = objCreator(5,10);
                var resu = result.Add();
            }

            #endregion

IL实现TryCatch

    #region Try Catch
            {
                var method = typeof(Console).GetMethod("WriteLine",new Type[] { typeof(string)});//输出字符串
                var method2 = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });//输出数字
                var dynamicMethod = typeBulder.DefineMethod("TryEx",MethodAttributes.Public,CallingConventions.Standard, typeof(string),new Type[] {typeof(object),typeof(object) });//构造方法
                var il = dynamicMethod.GetILGenerator();
                var local = il.DeclareLocal(typeof(string));//本地string类型变量
                var ex = typeof(Exception);
                var localEx = il.DeclareLocal(ex);//本地Exception类型变量
                var str = ex.GetMethod("ToString");//tostring方法
                var exInstance = new Exception();
                var localInt = il.DeclareLocal(typeof(int));//本地int变量
                il.BeginExceptionBlock();//构造try块
                il.Emit(OpCodes.Ldarg_1);//加载第一个变量
                il.Emit(OpCodes.Unbox_Any,typeof(int));//加载第一个变量并且将obj转为int
                il.Emit(OpCodes.Ldarg_2);//加载第二个变量并且将obj转为int
                il.Emit(OpCodes.Unbox_Any, typeof(int));//加载第二个变量并且将obj转为int
                il.Emit(OpCodes.Add);//相加
                il.Emit(OpCodes.Stloc,2);//赋值给本地第二个int变量
                il.Emit(OpCodes.Ldloc, 2);//加载本地第二个int变量
                il.Emit(OpCodes.Call, method2);//输出
                il.Emit(OpCodes.Ldstr, "正常执行");//加载字符串
                il.Emit(OpCodes.Stloc,0);//赋值给第0个变量
                il.BeginCatchBlock(ex);//构造catch块
                il.Emit(OpCodes.Stloc,1);//将ex赋值给本地exception变量
                il.Emit(OpCodes.Ldloc,1);
                il.Emit(OpCodes.Callvirt, str);//加载本地ex变量并且tostring一下
                il.Emit(OpCodes.Call, method);//输出异常信息
                il.Emit(OpCodes.Ldstr, "非正常执行");//加载结果字符串
                il.Emit(OpCodes.Stloc, 0);//赋值给第0个变量
                il.Emit(OpCodes.Rethrow);//抛出异常 就是throw
                il.EndExceptionBlock();//结束catch块
                il.Emit(OpCodes.Ldloc,0);//加载第0个字符串变量
                il.Emit(OpCodes.Ret);//返回结果
                var type = typeBulder.CreateType();
                var instance = Activator.CreateInstance(type);
                var mh = type.GetMethod("TryEx");
               var ttt= mh.Invoke(instance, new object[] { 10,new TestNewobj(1,1)});//此处可以修改为其他类型的变量,testnewobj是我测试用
            }
            #endregion

好了,今天的分享就结束了,后续会持续更新,欢迎大家关注,