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

相关文章

Ubuntu固定虚拟机ip地址的方法教程

《Ubuntu固定虚拟机ip地址的方法教程》本文详细介绍了如何在Ubuntu虚拟机中固定IP地址,包括检查和编辑`/etc/apt/sources.list`文件、更新网络配置文件以及使用Networ... 1、由于虚拟机网络是桥接,所以ip地址会不停地变化,接下来我们就讲述ip如何固定 2、如果apt安

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep