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

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

指令:

  • .field定义类成员。和关键字publicprivatestatic等一起使用。

命令:

  • 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

}

Downloads

Download source - 43 Kb

posted on 2007-08-16 10:52  永红  阅读(3019)  评论(15编辑  收藏  举报