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

相关文章

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

电脑提示xlstat4.dll丢失怎么修复? xlstat4.dll文件丢失处理办法

《电脑提示xlstat4.dll丢失怎么修复?xlstat4.dll文件丢失处理办法》长时间使用电脑,大家多少都会遇到类似dll文件丢失的情况,不过,解决这一问题其实并不复杂,下面我们就来看看xls... 在Windows操作系统中,xlstat4.dll是一个重要的动态链接库文件,通常用于支持各种应用程序

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根