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

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

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.