1、MSIL教程基本概念微软中间语言(MSIL) 是一种语言,是许多编译器(C#,VB.NET等)的输出中间语言反汇编器(ILDasm) 让用户以人可阅读的格式查看MSIL代码。 中间语言编译器(ILAsm) 从MSIL语言生成可执行文件 存放路径: WINNT Microsoft.NET Framework vn.nn.nn语言参考 所有MSIL指令的说明FrameworkSDKTool Developers GuidedocsPartition II Metadata.docMSIL命令的完整列表FrameworkSDKTool Developers GuidedocsPartition II
2、I CIL.doc一般信息在MSIL中,所有的操作都在栈上完成。当调用一个函数的时候,其参数和局部变量都被分配到栈上。函数的代码从该栈开始,把一些值压入栈,对这些值进行一些操作,从栈上取出值。执行MSIL命令和函数由3个步骤完成Step1 把命令操作数和函数参数压入栈(ld命令)。Step2 执行命令或者调用函数。命令或函数从栈中取出他们的操作数(参数)并把他们压入结果栈(返回值)。Step3 从栈中读取结果值(st命令)。注意:上面的步骤是可选的,例如void函数不会压入一个结果值到栈。栈包含值类型对象和引用类型对象 引用类型对象本身保存在堆中示例项目打印字符串用到的MSIL指令.entry
3、point 定义程序的入口点,该函数在程序启动的时候由.NET 运行库调用.maxstack 定义函数代码所用堆栈的最大深度。用到的MSIL命令ldstr string 把一个字符串常量装入堆栈。call function(parameters) 调用静态函数,函数的参数必须在函数调用前装入堆栈。pop 取出栈顶的值,当我们不需要把值存入变量时使用。ret 从一个函数中返回。.assembly PrintString /* Console.WriteLine(Hello, World)*/.method staticpublicvoid main() il managed .entrypoin
4、t / 该函数是程序的入口 .maxstack 8 / * / Console.WriteLine(Hello, World); / * ldstr Hello, World / 把字符串压入堆栈 / 调用静态的System.Console.Writeline函数 / (函数移除栈顶的字符串) call void mscorlibSystem.Console:WriteLine (class System.String) / * ldstr Press Enter to continue call void mscorlibSystem.Console:WriteLine (class Sys
5、tem.String) / 调用 System.Console.Read 函数 call int32 mscorlibSystem.Console:Read() / pop 指令移除栈顶元素 / (移除由Read()函数返回的数字 pop / * ret赋值该程序给一个变量赋与int值并把它打印到控制台窗口用到的MSIL命令ldc.i4.n 把一个 32位的常量(n从0到8)装入堆栈stloc.n 把一个从堆栈中返回的值存入第n(n从0到8)个局部变量.assembly XequalN / int x;/ x = 7;/ Console.WriteLine(x);.method staticp
6、ublicvoid main() il managed .entrypoint .maxstack 8 .locals init (0 int32 x)/ 分配一个局部变量 / * / x = 7; / * ldc.i4.7 / 把常量装入堆栈 stloc.0 / 把堆栈中的值存入第0个变量 / * / Console.WriteLine(x); / * ldloc.0 / 把第0个变量转入堆栈 call void mscorlibSystem.Console:WriteLine(int32) ret数据运算本程序从控制台读取2个数字,对它们进行简单的运算,然后显示结果。要用到的MSIL命令a
7、dd 2个值相加。命令的参数必须在调用前装入堆栈,该函数从堆栈中移除参数并把运算后的结果压入堆栈。 sub 2个值相减。 mul 2个值相乘。 .assembly Operations /*/ 程序的C#代码: int x, y, z; string s; Console.WriteLine(Enter x:); s = Console.ReadLine(); x = Int32.Parse(s); Console.WriteLine(Enter y:); s = Console.ReadLine(); y = Int32.Parse(s); z = x + y; Console.Write(
8、x + y = ); Console.Write(z); Console.WriteLine(); z = x - y; Console.Write(x - y = ); Console.Write(z); Console.WriteLine(); z = x * y; Console.Write(x * y = ); Console.Write(z); Console.WriteLine();*/.method staticpublicvoid main() il managed .entrypoint .maxstack 8 .locals init (0 int32 x, 1 int32
9、 y, 2 int32 z, 3 string s) / * / Console.WriteLine(Enter x:); / * ldstr Enter x: / 把字符装入堆栈call void mscorlibSystem.Console:WriteLine(string) / * / s = Console.ReadLine(); / * call string mscorlibSystem.Console:ReadLine() stloc.3 / 把值存入第3个变量 / * / x = Int32.Parse(s); / * ldloc.3 / 把第3个变量装入堆栈 / 调用 Sys
10、tem.Int32:Parse(string)函数 / 把字符串从堆栈中移除并把解析的结果int值压入堆栈 call int32 mscorlibSystem.Int32:Parse(string) stloc.0 / 把值存入第0个变量 / * / 和变量y的一些运算 / * ldstr Enter y: / 装入字符串 call void mscorlibSystem.Console:WriteLine(string) / 调用 call string mscorlibSystem.Console:ReadLine() / 调用 stloc.3 /把值存入第3个变量 ldloc.3 /把第
11、3个变量装入堆栈 call int32 mscorlibSystem.Int32:Parse(string) / 调用 stloc.1 /把值存入第1个变量 / * / z = x + y; / * ldloc.0 /把第0个变量装入堆栈 ldloc.1 /把第1个变量装入堆栈 / 把这2个值从堆栈中移除,把结果压入堆栈add stloc.2 /把值存入第2个变量 / * / Console.Write(x + y = ); / * ldstr x + y = / load string onto stack call void mscorlibSystem.Console:Write(str
12、ing) / * / Console.Write(z); / * ldloc.2 /把第2个变量装入堆栈 call void mscorlibSystem.Console:Write(int32) / * / Console.WriteLine(); / * ldstr /装入字符串 call void mscorlibSystem.Console:WriteLine(string) /相减和相乘运算过程与上面相同 ret数组本程序分配一个int型的数组并给他的元素赋值,然后打印出元素和数组的长度。要用到的MSIL命令newarr type 生成一个元素类型为type 的数组。数组的大小必须在
13、调用该命令前装入堆栈。该命令会把一个数组的引用装入堆栈。stelem.i4 给一个数组成员赋值。数组的引用、下标和值必须在调用该命令前装入堆栈。ldelema type 把数组元素的地址装入堆栈。数组的引用和下标必须在调用该命令前装入堆栈。地址用来调用非静态函数(参见后面)。ldlen 把数组的长度装入堆栈。数组的引用必须在调用该命令前装入堆栈。ldloca.s variable 把变量的地址装入堆栈。ldc.i4.s value 把一个Int32的常量装入堆栈(用于大于8位的数)。conv.i4 把堆栈中值转换成Int32类型。call instance function(arguments
14、) 调用类的非静态函数。在调用一个非静态函数之前,我们必须把某个类的实例的地址和函数的参数装入堆栈。在本例中,地址通过ldelema和ldloca 命令装入。.assembly Array1 /*/ This program works as C# code:int x = new int5;x0 = 10;x1 = 20;Console.WriteLine(x0 = + x0.ToString();Console.WriteLine(x1 = + x1.ToString();Console.WriteLine(Array length = + x.Length.ToString();*/.m
15、ethod staticpublicvoid main() il managed .entrypoint .maxstack 8 .locals init (0 int32 x, 1 int32 tmp) / 由编译器生成 / * / x = new int5; / * ldc.i4.5 / 把常量装入堆栈。 / 生成数组,并把他的引用压入堆栈 newarr mscorlibSystem.Int32 / 把数组从堆栈中取出,存入第0个局部变量中 stloc.0 / * / x0 = 10; / * ldloc.0 / 把第0个局部变量装入堆栈(数组) ldc.i4.0 / 把常量0装入堆栈(下
16、标) ldc.i4.s 10 / 把常量10装入堆栈(值) stelem.i4 / arrayindex = value / 对数组的其余元素进行同样的操作 / * / Console.WriteLine(x0 = + x0.ToString(); / * ldstr x0 = / 堆栈:x0 = (堆栈由局部变量表示) ldloc.0 / 把第0个变量装入堆栈 ldc.i4.0 / 把第1个变量装入堆栈 / 堆栈: x0 = - x - 0 / 把元素的地址装入堆栈 ldelema mscorlibSystem.Int32 / 堆栈: x0 = - 指向一个Int32的指针 / 10 / 调
17、用实例函数System.Int32:ToString(). call instance string mscorlibSystem.Int32:ToString() / 堆栈: x0 = - 10 / 调用静态函数System.String:Concat(string, string) call string mscorlibSystem.String:Concat (string, string) / 堆栈: x0 = 10 / 调用静态函数 System.Console:WriteLine(string) call void mscorlibSystem.Console:WriteLine
18、(string) / 堆栈: 空 /对数组的其余元素进行同样的操作 / * / Console.WriteLine(Array length = + x.Length.ToString(); / * ldstr Array length = / 堆栈: Array length = ldloc.0 / 把第0个变量装入堆栈 / 堆栈: Array length = - x Ldlen / 把数组的长度装入堆栈 / 堆栈: Array length = - 5 conv.i4 / 把栈顶的值转换为Int32,并把他装入堆栈 / 堆栈: Array length = - 5 stloc.1 / 把刚才的值存入第1个局部变量(tmp) / 堆栈: Array length = ldloca.s tmp /把变量tmp的地址装入堆栈 / 堆栈: Array length = - &tmp call instance string mscorlibSystem.Int32:ToString() / 堆栈: Array length = - 5 call string mscorlibSystem.String:Concat (string, string) / 堆栈: Array length = 5 call void msco
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2