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

2024-04-17 01:38
文章标签 异常 教程 处理 msil

本文主要是介绍MSIL 教程(三):类和异常处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

续上文【翻译】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
}
Downloads
Download source - 43 Kb

 

这篇关于MSIL 教程(三):类和异常处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/910471

相关文章

详解如何在SpringBoot控制器中处理用户数据

《详解如何在SpringBoot控制器中处理用户数据》在SpringBoot应用开发中,控制器(Controller)扮演着至关重要的角色,它负责接收用户请求、处理数据并返回响应,本文将深入浅出地讲解... 目录一、获取请求参数1.1 获取查询参数1.2 获取路径参数二、处理表单提交2.1 处理表单数据三、

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

ubuntu20.0.4系统中安装Anaconda的超详细图文教程

《ubuntu20.0.4系统中安装Anaconda的超详细图文教程》:本文主要介绍了在Ubuntu系统中如何下载和安装Anaconda,提供了两种方法,详细内容请阅读本文,希望能对你有所帮助... 本文介绍了在Ubuntu系统中如何下载和安装Anaconda。提供了两种方法,包括通过网页手动下载和使用wg

如何在Ubuntu上安装NVIDIA显卡驱动? Ubuntu安装英伟达显卡驱动教程

《如何在Ubuntu上安装NVIDIA显卡驱动?Ubuntu安装英伟达显卡驱动教程》Windows系统不同,Linux系统通常不会自动安装专有显卡驱动,今天我们就来看看Ubuntu系统安装英伟达显卡... 对于使用NVIDIA显卡的Ubuntu用户来说,正确安装显卡驱动是获得最佳图形性能的关键。与Windo

Spring Boot Controller处理HTTP请求体的方法

《SpringBootController处理HTTP请求体的方法》SpringBoot提供了强大的机制来处理不同Content-Type​的HTTP请求体,这主要依赖于HttpMessageCo... 目录一、核心机制:HttpMessageConverter​二、按Content-Type​处理详解1.

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删