• IL程序基本结构


    IL代码大致分为三部分:程序头,各类声明,代码段

    程序头:主要是包括编译后生成的可执行文件的一些属性的定义,一般三个关键字

    .assembly 声明本程序集名称

    .assembly extern 声明外部程序集名称

    .module  声明主模块名称

    各类声明:

    .namespace 名称空间声明

    .class 类声明

    .method 方法声明

    .field  字段声明

    .data 数据声明

    .custom 自定义属性声明

    代码段:

    主要由MSIL指令以及个别关键字构成,通常一个IL指令由操作码(opcode)和指令参数(操作数operrand)构成,操作码长度为1或2字节,当为2字节时,第一个字节总是0xFE

      流程控制指令:

        1.直接跳转指令

         br 从当前位置移动到指定的位置

         br .s   br的短指令格式

       2.条件跳转指令

          brfalse  value为0则跳转

          brfalse.s    短指令格式

          brtrue 不为0跳转

          brtrue.s  短指令格式

      3.比较跳转

         beq  等于跳转   beq.s

         bne.un 不等于跳转   bne.nu.s  无符号

         bge[.un.s] 大于或等于 

         bgt[.un.s]     大于则跳转  

         ble[.un.s]     小于等于跳转 

         blt[.un.s]   小于跳转 

         un 标识无符号 s标识短指令

      4.选择指令

        switch

      5中断指令

        break

      6 托管异常指令

         leave[.s] 清空堆栈,跳至当前指令的偏移处。用于从try。。catch跳出

         endfilter 表示filter块的终结。

         endfinally 表示finally或fault终结,并清空堆栈

      7 返回指令

         ret  从一个方法返回

    算术指令

      1.堆栈操作

         nop 空指令 无任何操作

         dup 赋值当前栈顶元素

         pop 出栈 堆栈为空时出错

       2.常数载入

          用于将常数入栈

         ldc.i4 载入int32

         ldc.i4.s 载入int8

         ldc.i4.ml 载入-1

         ldc.i4.[0 ~8] 载入0~8;

         ldc.i8 载入int64

         ldc.r4 载入float32

         ldc.r8 载入float64

    3.间接载入

        间接载入指令从栈顶取出一个托管指针(&类型)或非托管指针(native int 类型),载入该指针所指向的数值,并入栈。指令中小数点后的名称表明了载入数据的类型

       ldind.i1/ ldind.u1 载入1字节无符号/有符号整数

       ldind.i2/ldind.u2  2字节

       ldind.i4/ldind.u4  4字节

       ldind.i8/ldind.u8  8字节

       ldind.i                载入native int 大小为当前系统的指针大小

        ldind.r4/ldind.r8 载入单精度/双精度浮点数据

        ldind.ref            载入引用对象

    4.间接存储

    间接存储从栈顶先后取出一个值和指针,并将改值存储至指针所指位置。

    stind.ref  存储一个对象引用

    stind.i1,i2,i4,i8 存储1.2.4.8字节整数

      stind.i存储一个指针大小的数据

      stind.r4,r8 存储单精度、双精度浮点数

    5.算数运算

       add 加   sub 减  mul 乘  div除法  rem 模运算 neg 取反运算

       两个特殊值:无限(infinity)和NaN(Not a Number)  0*infinity=NaN

       0/0=NaN infinity/infinity=NaN x/infinity=0

      

    6.位操作

      and 按位与 or 按位或  xor  按位异或  not 按位求反

    7 移位操作

       shl 左移位 shr 右移位  shr.un无符号右移位

    8.转换指令

        从栈顶取值,进行相应转换,将结果入栈。

        conv.[类型]

        conv.ovf.[类型]

    9.逻辑条件检测

       ceq 是否相等  cgt[.un] 是否大于  clt [.un]是否小于  ckfiniter 取栈顶元素。当为NaN infinity抛出异常,否则入栈

    10.块操作

        cpblk 复制一块内存  initblk 初始化一块内存

    参数、局部变量与字段寻址

    方法参数载入

      ldarg 载入一个方法参数

      ldarg.s短指令格式 

      ldarg[.0~4]载入第0~4个参数

    方法参数地址载入 :ldarga[.s] 载入参数并入栈

    方法参数存储:      starg[.s]   从栈顶取一个参数并存入参数

    方法参数列表         arglist  取得方法参数句柄 。。

    局部变量载入  ldloc[.s][.0~3]载入第n个局部变量

    局部变量引用载入 ldloca[.s] 载入局部变量的引用并入栈

    局部变量保存   stloc[.s] 从栈顶取值并存入局部变量

    局部内存块分配  localloc  分配一块局部内存块

    方法调用

      直接调用:

    jmp <token> (..) 放弃当前方法执行,直接跳转至 token所指目标方法。

      call <token>(..) 以不通过v-able的方式调用一个instance或static方法

      callvirt<token>通过实例的v-table调用oken所指的方法。

    间接调用

      ldftn   ldvirtftn   calli

    尾部调用

    tail

    类与值操作

    ldnull 读取空的对象引用并入栈

    ldobj  从堆栈获取值类型的托管指针

    stobj 依次从堆栈取得值类型的值

    ldstr  读取一个字符串

    newobj 分配内存创建某个类的新实例

    box 装箱 unbox 拆箱

    image

  • 相关阅读:
    mysql8.0.x中datasource信息
    IDEA关联mysql失败Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'
    SpringSecurity配置文件
    druid监控
    Redis安装教程
    一个简单的springboot+mybatis-plus+thymeleaf的学生管理系统
    RestFul风格
    Vue利用v-for渲染时表单信息出不来
    springboot项目Invalid bound statement (not found): com.xxxx.dao.xxxDAO.xxx解决方法
    JSON
  • 原文地址:https://www.cnblogs.com/ac1985482/p/1992484.html
Copyright © 2020-2023  润新知