首页 > 代码库 > MSIL 教程(三):类和异常处理(转)

MSIL 教程(三):类和异常处理(转)

转自:http://www.cnblogs.com/Yahong111/archive/2007/08/16/857771.html

续上文【翻译】MSIL 教程(二):数组、分支、循环、使用不安全代码和如何调用Win32 API ,本文继续讲解类和异常处理。谨以这三篇译文纪念29年前的今日,那个让母亲今生难以忘记的幸福而又痛苦的日子。

在前面的程序中,我们在Main函数中调用类函数,在本程序中,我们将徐希如何定义类。本程序包含2个类: Class1和SampleClass,Class1带有函数Main,在Main中生成SampleClass的一个实例。

指令:

  • .field—定义类成员。和关键字public、private、static等一起使用。

命令:

  • stsfld static field—用堆栈中的值替换静态字段的值。
  • ldfld field—把一个非静态字段装入堆栈。类实例的地址必须在调用本命令之前装入堆栈。
  • ldarg.n—把第n个参数装入堆栈。在非静态函数中,第0个参数是一个隐含的参数,代表this。
  • newobj constructor—用构造函数constructor生成一个类的实例。构造函数的参数必须在调用本函数之前先装入堆栈。一个类的实例会被生成并装入堆栈。
  • callvirt instance function—调用一个对象的后期绑定方法。

代码:

.assembly Classes {}/*    class SampleClass    {        private int m_n;        private string m_s;        public static int nStatic = 10;        public SampleClass(int n, string s)        {            m_n = n;            m_s = s;        }         public int Number        {            get            {                return m_n;            }        }         public string String        {            get            {                return m_s;            }        }    };     class Class1    {        [STAThread]        static void Main(string[] args)        {            SampleClass o = new SampleClass(1, "Sample");            Console.WriteLine(SampleClass.nStatic.ToString());            Console.WriteLine(o.Number.ToString());            Console.WriteLine(o.String);        }    }*/  .class private auto ansi beforefieldinit SampleClass       extends [mscorlib]System.Object{    .field private int32 m_n              // private int m_n;    .field private string m_s             // private string m_s;    .field public static int32 nStatic    // public static int nStatic;     // 该私有静态构造函数由编译器生成    // (用以初始化类的静态成员)    .method private hidebysig specialname rtspecialname static        void  .cctor() cil managed    {        .maxstack  8         // *************************************************        // nStatic = 10        // *************************************************        ldc.i4.s 10            // 把常量装入堆栈        // stsfld 命令把静态字段的值替换成堆栈中的值        stsfld     int32 SampleClass::nStatic         ret    }     // 构造函数    // public SampleClass(int n, string s)    //    .method public hidebysig specialname rtspecialname        instance void  .ctor(int32 n, string s) cil managed    {        .maxstack  8         // *************************************************        // 调用基类的构造函数        // *************************************************        ldarg.0         // 把第0个参数装入堆栈(隐含指针this)        // 调用类Object的构造函数        call       instance void [mscorlib]System.Object::.ctor()         // *************************************************        // m_n = n        // *************************************************        ldarg.0         // 把第0个参数装入堆栈(隐含指针this)        ldarg.1         // 把第1个参数装入堆栈(n)        // 把n的值存入this.m_n        stfld      int32 SampleClass::m_n         // *************************************************        // m_s = s        // *************************************************        ldarg.0         //把第0个参数装入堆栈(隐含指针this)        ldarg.2         //把第2个参数装入堆栈(s)        // 把s的值存入this.m_s        stfld      string SampleClass::m_s         ret    }     // 数字型属性    .property instance int32 Number()    {        // 调用 get_Number        .get instance int32 SampleClass::get_Number()    }     .method public hidebysig specialname instance int32        get_Number() cil managed    {        .maxstack  8         // 由编译器生成的变量        // 译注:实际上,只有Debug版的才有,Release版的就直接返回m_n        .locals ([0] int32 tmp)         // *************************************************        // 返回 m_n;        // *************************************************        ldarg.0                  // 装入第0个参数(this)        ldfld      int32 SampleClass::m_n                  // 装入由堆栈栈顶指针指向的对象的字段        stloc.0                  // 存入第0个变量        ldloc.0                  // 把第0个变量装入堆栈(函数的返回值)        ret    }     // 字符型属性    .property instance string String()    {        .get instance string SampleClass::get_String()    }     .method public hidebysig specialname instance string            get_String() cil managed    {        .maxstack  8         // 由编译器生成的变量        .locals ([0] string tmp)         ldarg.0              // 装入第0个参数(this)        ldfld      string SampleClass::m_s             // 装入由堆栈栈顶指针指向的对象的字段        stloc.0             // 存入第0个变量        ldloc.0             // 把第0个变量装入堆栈(函数的返回值)        ret    }}  .class private auto ansi beforefieldinit Class1       extends [mscorlib]System.Object{    // public的缺省构造函数    .method public hidebysig specialname rtspecialname        instance void  .ctor() cil managed    {        .maxstack  8         // *************************************************        // 调用基类构造函数        // *************************************************        ldarg.0                          // 装入thisr        call       instance void [mscorlib]System.Object::.ctor()                          // 类Objectr的构造函数         ret    }     // Main 函数    .method private hidebysig static void  Main(string[] args)            cil managed    {        // 本方法为程序的入口点        .entrypoint         // 自定义属性        .custom instance void [mscorlib]System.                STAThreadAttribute::.ctor() = ( 01 00 00 00 )         .maxstack  8         .locals ([0] class SampleClass o,                 [1] int32 tmp)          // 由编译器生成         // *************************************************        // o = new SampleClass(1, "Sample");        // *************************************************        ldc.i4.1                        // 把常量1装入堆栈        ldstr      "Sample"             // 把字符常量装入堆栈        // 通过传入堆栈中的2个参数生成一个SampleClass的对象,        // 并把他装入堆栈        newobj     instance void SampleClass::.ctor(int32, string)        stloc.0                         // 存入第0个变量         // *************************************************        // 访问静态类成员        // Console.WriteLine(SampleClass.nStatic.ToString());        // *************************************************         //把静态字段的地址装入堆栈        ldsflda    int32 SampleClass::nStatic        // 为堆栈中的对象调用Int32::ToString        call       instance string [mscorlib]System.Int32                            ::ToString()        // 调用静态的WriteLine,其传入参数是堆栈中的字符串        call       void [mscorlib]System.Console                   ::WriteLine(string)         // *************************************************        // 调用实例函数        // Console.WriteLine(o.Number.ToString());        // *************************************************        ldloc.0                 // 装入第0个变量        // 调用堆栈中对象的函数        call   instance int32 SampleClass::get_Number()        stloc.1                         // 存入第1个变量        ldloca.s  tmp                   // 把地址装入堆栈        call       instance string [mscorlib]System.Int32                            ::ToString()        call       void [mscorlib]System.Console                        ::WriteLine(string)         // *************************************************        // 调用实例函数        // Console.WriteLine(o.String);        // *************************************************        ldloc.0        callvirt   instance string SampleClass::get_String()        call       void [mscorlib]System.Console                        ::WriteLine(string)         // *************************************************        ldstr "Press Enter to continue"        call   void [mscorlib]System.Console                    ::WriteLine(class System.String)        call int32 [mscorlib]System.Console::Read()        pop        // *************************************************         ret    }}

异常处理

本程序使2个数相除,捕捉其除0异常。try/catch 块在MSIL中看起来像C#中的一样。

命令:

  • leave.s label—离开try/catch等保护块。

代码:

.assembly Exception {} /*            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);             try            {                z = x / y;                 Console.WriteLine(z.ToString());            }            catch (Exception e)            {                Console.WriteLine(e.Message);            } */ .method static public void main() il managed{    .entrypoint    .maxstack 8     .locals ([0] int32 x,             [1] int32 y,             [2] int32 z,             [3] string s,             [4] class [mscorlib]System.Exception e)     //输入 x, y ...     .try    {        // *************************************************        // z = x / y;        // *************************************************        ldloc.0                 // 装入第0个变量        ldloc.1                 // 装入第1个变量        div                     // 相除        stloc.2                 // 把结果存入第2个变量         // *************************************************        // Console.WriteLine(z.ToString());        // *************************************************        ldloca.s   z            // 装入z的地址        call       instance string [mscorlib]System.Int32                                   ::ToString()        call       void [mscorlib]System.Console                                   ::WriteLine(string)         leave.s    END_TRY_CATCH        // 退出try    }    catch [mscorlib]System.Exception    {        stloc.s    e        // 存入由堆栈抛出的异常         // *************************************************        // Console.WriteLine(e.Message);        // *************************************************        ldloc.s    e                // load e        callvirt   instance string [mscorlib]System.Exception                                   ::get_Message()        call       void [mscorlib]System.Console                                   ::WriteLine(string)        leave.s    END_TRY_CATCH        // 退出catch块    } END_TRY_CATCH:     ret}

 

MSIL 教程(三):类和异常处理(转)