[No0000152]C#基础之IL,轻松读懂IL

您所在的位置:网站首页 ceq是什么缩写 [No0000152]C#基础之IL,轻松读懂IL

[No0000152]C#基础之IL,轻松读懂IL

2024-07-10 11:52:12| 来源: 网络整理| 查看: 265

先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用。到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西。其实IL本身逻辑很清楚,主要是把指令的意思搞明白就好办了。记指令只要记住几个规律就好,我把它们分为三类。

第一类 :直观型

这一类的特点是一看名字就知道是干嘛的,不需要多讲,如下:

名称

说明

Add 

将两个值相加并将结果推送到计算堆栈上。

Sub 

从其他值中减去一个值并将结果推送到计算堆栈上。

Div 

将两个值相除并将结果作为浮点(F 类型)或商(int32 类型)推送到计算堆栈上。

Mul 

将两个值相乘并将结果推送到计算堆栈上。

Rem 

将两个值相除并将余数推送到计算堆栈上。

Xor 

计算位于计算堆栈顶部的两个值的按位异或,并且将结果推送到计算堆栈上。

And 

计算两个值的按位"与"并将结果推送到计算堆栈上。

Or 

计算位于堆栈顶部的两个整数值的按位求补并将结果推送到计算堆栈上。

Not 

计算堆栈顶部整数值的按位求补并将结果作为相同的类型推送到计算堆栈上。

Dup 

复制计算堆栈上当前最顶端的值,然后将副本推送到计算堆栈上。

Neg 

对一个值执行求反并将结果推送到计算堆栈上。

Ret 

从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

Jmp 

退出当前方法并跳至指定方法。

Newobj 

New Object创建一个值类型的新对象或新实例,并将对象引用推送到计算堆栈上。

Newarr 

New Array将对新的从零开始的一维数组(其元素属于特定类型)的对象引用推送到计算堆栈上。

Nop 

如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。Debug下的

Pop 

移除当前位于计算堆栈顶部的值。

Initobj 

Init Object将位于指定地址的值类型的每个字段初始化为空引用或适当的基元类型的 0。

Isinst 

Is Instance测试对象引用是否为特定类的实例。

Sizeof 

将提供的值类型的大小(以字节为单位)推送到计算堆栈上。

Box

将值类转换为对象引用。

Unbox 

将值类型的已装箱的表示形式转换为其未装箱的形式。

Castclass 

尝试将引用传递的对象转换为指定的类。

Switch 

实现跳转表。

Throw 

引发当前位于计算堆栈上的异常对象。

Call 

调用由传递的方法说明符指示的方法。

Calli 

通过调用约定描述的参数调用在计算堆栈上指示的方法(作为指向入口点的指针)。

Callvirt 

对对象调用后期绑定方法,并且将返回值推送到计算堆栈上。

强调一下,有三种call,用的场景不太一样:

Call:常用于调用编译时就确定的方法,可以直接去元数据里找方法,如静态函数,实例方法,也可以call虚方法,不过只是call这个类型本身的虚方法,和实例的方法性质一样。另外,call不做null检测。

Calli: MSDN上讲是间接调用指针指向的函数,具体场景没见过,有知道的朋友望不吝赐教。

Callvirt: 可以调用实例方法和虚方法,调用虚方法时以多态方式调用,不能调用静态方法。Callvirt调用时会做null检测,如果实例是null,会抛出NullReferenceException,所以速度上比call慢点。

第二类:加载(ld)和存储(st)

我们知道,C#程序运行时会有线程栈把参数,局部变量放上来,另外还有个计算栈用来做函数里的计算。所以把值加载到计算栈上,算完后再把计算栈上的值存到线程栈上去,这类指令专门干这些活。

比方说 ldloc.0:

这个可以拆开来看,Ld打头可以理解为Load,也就是加载;loc可以理解为local variable,也就是局部变量,后面的 .0表示索引。连起来的意思就是把索引为0的局部变量加载到计算栈上。对应的 ldloc.1就是把索引为1的局部变量加载到计算栈上,以此类推。

知道了Ld的意思,下面这些指令 也就很容易理解了。

ldstr = load string,

ldnull = load null, 

ldobj = load object,

ldfld = load field,

ldflda = load field address,

ldsfld = load static field,

ldsflda = load static field address,

ldelem = load element in array,

ldarg = load argument,

ldc 则表示加载数值,如ldc.i4.0,

 

关于后缀 

.i[n]:[n]表示字节数,1个字节是8位,所以是8*n的int,比如i1, i2, i4, i8,i1就是int8(byte), i2是int16(short),i4是int32(int),i8是int64(long)。

相似的还有.u1 .u2 .u4 .u8  分别表示unsigned int8(byte), unsigned int16(short), unsigned int32(int), unsigned int64(long);

.R4,.R8 表示的是float和double。

.ovf (overflow)则表示会进行溢出检查,溢出时会抛出异常;

.un (unsigned)表示无符号数;

.ref (reference)表示引用;

.s (short)表示短格式,比如说正常的是用int32,加了.s的话就是用int8;

.[n] 比如 .1,.2 等,如果跟在i[n]后面则表示数值,其他都表示索引。如 ldc.i4.1就是加载数值1到计算栈上,再如ldarg.0就是加载第一个参数到计算栈上。

 

 

ldarg要特别注意一个问题:如果是实例方法的话ldarg.0加载的是本身,也就是this,ldarg.1加载的才是函数的第一个参数;如果是静态函数,ldarg.0就是第一个参数。

 

与ld对应的就是st,可以理解为store,意思是把值从计算栈上存到变量中去,ld相关的指令很多都有st对应的,比如stloc, starg, stelem等,就不多说了。

 

第三类:比较指令,比较大小或判断bool值

有一部分是比较之后跳转的,代码里的 if 就会产生这些指令,符合条件则跳转执行另一些代码:

以b开头:beq, bge, bgt, ble, blt, bne

先把b去掉看看:eq: equivalent with, == ge: greater than or equivalent with , >= 

gt: greater than , > le: less than or equivalent with, 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭