日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

通用中间语言(CIL)

發(fā)布時(shí)間:2024/6/21 综合教程 35 生活家
生活随笔 收集整理的這篇文章主要介紹了 通用中间语言(CIL) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.前言

在編寫程序時(shí),往往需要比較多種聲明或算法的性能,這可以通過查看程序的 IL 代碼分析比較其過程及步驟的方式實(shí)現(xiàn)。

在編譯使用 .NET Framework 庫代碼時(shí),不是立即創(chuàng)建專用于操作系統(tǒng)的本機(jī)代碼,而是把代碼編譯為通用中間語言(Common Intermediate Language,CIL)代碼,這些代碼并非專用于任何一種操作系統(tǒng),也非專用于C#,其他 .NET 語言(如 VB)也會(huì)在第一階段編譯為這種語言。開發(fā) C# 應(yīng)用程序時(shí),這個(gè)編譯步驟由 VS 完成。IL主要包含一些元數(shù)據(jù)和中間語言指令。(CIL 也可稱為 MSIL 或 IL)

2.查看 IL 代碼

查看 IL 代碼的步驟如下:

1)打開 Developer Command Prompt for VS 2017

2)在 CMD 窗口中輸入命令 ildasm

3)以上步驟將彈出以下窗口,在 File 下打開已編譯的 exe 文件或 dll 文件,左圖為 IL 使用 ILDasm 反編譯的結(jié)果,右圖為 ILDasm 圖標(biāo)含義:

其對(duì)應(yīng)源碼如下:

namespace ConsoleApp4
{
    class Person
    {
        string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public void SayNum(int num)
        {
            Console.WriteLine($"the num is {num}");
        }
        public static void Method()
        {
            Console.WriteLine("I am a person.");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            p.Name = "kyle";
            p.SayNum(10);
            Person.Method();
            Console.ReadKey();
        }
    }
}

View Code

3.分析 IL 代碼

在分析 IL 代碼之前,應(yīng)對(duì)程序執(zhí)行在內(nèi)存中的分配有一定的了解,

Managed Heap:托管堆動(dòng)態(tài)配置(Dynamic Allocation)的內(nèi)存,用來分配引用類型的對(duì)象,由Garbage Collector(GC)在執(zhí)行時(shí)自動(dòng)管理,整個(gè)Process共用一個(gè)Managed Heap。
Call Stack:調(diào)用堆棧是一個(gè)方法列表,按調(diào)用順序保存所有在運(yùn)行期被調(diào)用的方法
Evaluation Stack:這是由.NET CLR在執(zhí)行時(shí)自動(dòng)管理的內(nèi)存,IL 里面的任何計(jì)算,都發(fā)生在 Evaluation Stack 上

IL 指令及其對(duì)應(yīng)說明如下所示:

名稱    說明
Add    將兩個(gè)值相加并將結(jié)果推送到計(jì)算堆棧上。
Add.Ovf    將兩個(gè)整數(shù)相加,執(zhí)行溢出檢查,并且將結(jié)果推送到計(jì)算堆棧上。
Add.Ovf.Un    將兩個(gè)無符號(hào)整數(shù)值相加,執(zhí)行溢出檢查,并且將結(jié)果推送到計(jì)算堆棧上。
And    計(jì)算兩個(gè)值的按位“與”并將結(jié)果推送到計(jì)算堆棧上。
Arglist    返回指向當(dāng)前方法的參數(shù)列表的非托管指針。
Beq    如果兩個(gè)值相等,則將控制轉(zhuǎn)移到目標(biāo)指令。
Beq.S    如果兩個(gè)值相等,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Bge    如果第一個(gè)值大于或等于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Bge.S    如果第一個(gè)值大于或等于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Bge.Un    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Bge.Un.S    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Bgt    如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Bgt.S    如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Bgt.Un    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Bgt.Un.S    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值大于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Ble    如果第一個(gè)值小于或等于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Ble.S    如果第一個(gè)值小于或等于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Ble.Un    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值小于或等于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Ble.Un.S    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)值時(shí),如果第一個(gè)值小于或等于第二個(gè)值,則將控制權(quán)轉(zhuǎn)移到目標(biāo)指令(短格式)。
Blt    如果第一個(gè)值小于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Blt.S    如果第一個(gè)值小于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Blt.Un    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值小于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令。
Blt.Un.S    當(dāng)比較無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值時(shí),如果第一個(gè)值小于第二個(gè)值,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Bne.Un    當(dāng)兩個(gè)無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值不相等時(shí),將控制轉(zhuǎn)移到目標(biāo)指令。
Bne.Un.S    當(dāng)兩個(gè)無符號(hào)整數(shù)值或不可排序的浮點(diǎn)型值不相等時(shí),將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Box    將值類轉(zhuǎn)換為對(duì)象引用(O 類型)。
Br    無條件地將控制轉(zhuǎn)移到目標(biāo)指令。
Br.S    無條件地將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Break    向公共語言結(jié)構(gòu) (CLI) 發(fā)出信號(hào)以通知調(diào)試器已撞上了一個(gè)斷點(diǎn)。
Brfalse    如果 value 為 false、空引用(Visual Basic 中的 Nothing)或零,則將控制轉(zhuǎn)移到目標(biāo)指令。
Brfalse.S    如果 value 為 false、空引用或零,則將控制轉(zhuǎn)移到目標(biāo)指令。
Brtrue    如果 value 為 true、非空或非零,則將控制轉(zhuǎn)移到目標(biāo)指令。
Brtrue.S    如果 value 為 true、非空或非零,則將控制轉(zhuǎn)移到目標(biāo)指令(短格式)。
Call    調(diào)用由傳遞的方法說明符指示的方法。
Calli    通過調(diào)用約定描述的參數(shù)調(diào)用在計(jì)算堆棧上指示的方法(作為指向入口點(diǎn)的指針)。
Callvirt    對(duì)對(duì)象調(diào)用后期綁定方法,并且將返回值推送到計(jì)算堆棧上。
Castclass    嘗試將引用傳遞的對(duì)象轉(zhuǎn)換為指定的類。
Ceq    比較兩個(gè)值。如果這兩個(gè)值相等,則將整數(shù)值 1 (int32) 推送到計(jì)算堆棧上;否則,將 0 (int32) 推送到計(jì)算堆棧上。
Cgt    比較兩個(gè)值。如果第一個(gè)值大于第二個(gè)值,則將整數(shù)值 1 (int32) 推送到計(jì)算堆棧上;反之,將 0 (int32) 推送到計(jì)算堆棧上。
Cgt.Un    比較兩個(gè)無符號(hào)的或不可排序的值。如果第一個(gè)值大于第二個(gè)值,則將整數(shù)值 1 (int32) 推送到計(jì)算堆棧上;反之,將 0 (int32) 推送到計(jì)算堆棧上。
Ckfinite    如果值不是有限數(shù),則引發(fā) ArithmeticException。
Clt    比較兩個(gè)值。如果第一個(gè)值小于第二個(gè)值,則將整數(shù)值 1 (int32) 推送到計(jì)算堆棧上;反之,將 0 (int32) 推送到計(jì)算堆棧上。
Clt.Un    比較無符號(hào)的或不可排序的值 value1 和 value2。如果 value1 小于 value2,則將整數(shù)值 1 (int32 ) 推送到計(jì)算堆棧上;反之,將 0 ( int32 ) 推送到計(jì)算堆棧上。
Constrained    約束要對(duì)其進(jìn)行虛方法調(diào)用的類型。
Conv.I    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 native int。
Conv.I1    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 int8,然后將其擴(kuò)展(填充)為 int32。
Conv.I2    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 int16,然后將其擴(kuò)展(填充)為 int32。
Conv.I4    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 int32。
Conv.I8    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 int64。
Conv.Ovf.I    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為有符號(hào) native int,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為有符號(hào) native int,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I1    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為有符號(hào) int8 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I1.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為有符號(hào) int8 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I2    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為有符號(hào) int16 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I2.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為有符號(hào) int16 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I4    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為有符號(hào) int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I4.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為有符號(hào) int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I8    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為有符號(hào) int64,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.I8.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為有符號(hào) int64,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為 unsigned native int,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為 unsigned native int,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U1    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為 unsigned int8 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U1.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為 unsigned int8 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U2    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為 unsigned int16 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U2.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為 unsigned int16 并將其擴(kuò)展為 int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U4    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為 unsigned int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U4.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為 unsigned int32,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U8    將位于計(jì)算堆棧頂部的有符號(hào)值轉(zhuǎn)換為 unsigned int64,并在溢出時(shí)引發(fā) OverflowException。
Conv.Ovf.U8.Un    將位于計(jì)算堆棧頂部的無符號(hào)值轉(zhuǎn)換為 unsigned int64,并在溢出時(shí)引發(fā) OverflowException。
Conv.R.Un    將位于計(jì)算堆棧頂部的無符號(hào)整數(shù)值轉(zhuǎn)換為 float32。
Conv.R4    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 float32。
Conv.R8    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 float64。
Conv.U    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 unsigned native int,然后將其擴(kuò)展為 native int。
Conv.U1    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 unsigned int8,然后將其擴(kuò)展為 int32。
Conv.U2    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 unsigned int16,然后將其擴(kuò)展為 int32。
Conv.U4    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 unsigned int32,然后將其擴(kuò)展為 int32。
Conv.U8    將位于計(jì)算堆棧頂部的值轉(zhuǎn)換為 unsigned int64,然后將其擴(kuò)展為 int64。
Cpblk    將指定數(shù)目的字節(jié)從源地址復(fù)制到目標(biāo)地址。
Cpobj    將位于對(duì)象(&、* 或 native int 類型)地址的值類型復(fù)制到目標(biāo)對(duì)象(&、* 或 native int 類型)的地址。
Div    將兩個(gè)值相除并將結(jié)果作為浮點(diǎn)(F 類型)或商(int32 類型)推送到計(jì)算堆棧上。
Div.Un    兩個(gè)無符號(hào)整數(shù)值相除并將結(jié)果 ( int32 ) 推送到計(jì)算堆棧上。
Dup    復(fù)制計(jì)算堆棧上當(dāng)前最頂端的值,然后將副本推送到計(jì)算堆棧上。
Endfilter    將控制從異常的 filter 子句轉(zhuǎn)移回公共語言結(jié)構(gòu) (CLI) 異常處理程序。
Endfinally    將控制從異常塊的 fault 或 finally 子句轉(zhuǎn)移回公共語言結(jié)構(gòu) (CLI) 異常處理程序。
Initblk    將位于特定地址的內(nèi)存的指定塊初始化為給定大小和初始值。
Initobj    將位于指定地址的值類型的每個(gè)字段初始化為空引用或適當(dāng)?shù)幕愋偷?0。
Isinst    測(cè)試對(duì)象引用(O 類型)是否為特定類的實(shí)例。
Jmp    退出當(dāng)前方法并跳至指定方法。
Ldarg    將參數(shù)(由指定索引值引用)加載到堆棧上。
Ldarg.0    將索引為 0 的參數(shù)加載到計(jì)算堆棧上。
Ldarg.1    將索引為 1 的參數(shù)加載到計(jì)算堆棧上。
Ldarg.2    將索引為 2 的參數(shù)加載到計(jì)算堆棧上。
Ldarg.3    將索引為 3 的參數(shù)加載到計(jì)算堆棧上。
Ldarg.S    將參數(shù)(由指定的短格式索引引用)加載到計(jì)算堆棧上。
Ldarga    將參數(shù)地址加載到計(jì)算堆棧上。
Ldarga.S    以短格式將參數(shù)地址加載到計(jì)算堆棧上。
Ldc.I4    將所提供的 int32 類型的值作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.0    將整數(shù)值 0 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.1    將整數(shù)值 1 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.2    將整數(shù)值 2 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.3    將整數(shù)值 3 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.4    將整數(shù)值 4 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.5    將整數(shù)值 5 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.6    將整數(shù)值 6 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.7    將整數(shù)值 7 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.8    將整數(shù)值 8 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.M1    將整數(shù)值 -1 作為 int32 推送到計(jì)算堆棧上。
Ldc.I4.S    將提供的 int8 值作為 int32 推送到計(jì)算堆棧上(短格式)。
Ldc.I8    將所提供的 int64 類型的值作為 int64 推送到計(jì)算堆棧上。
Ldc.R4    將所提供的 float32 類型的值作為 F (float) 類型推送到計(jì)算堆棧上。
Ldc.R8    將所提供的 float64 類型的值作為 F (float) 類型推送到計(jì)算堆棧上。
Ldelem    按照指令中指定的類型,將指定數(shù)組索引中的元素加載到計(jì)算堆棧的頂部。
Ldelem.I    將位于指定數(shù)組索引處的 native int 類型的元素作為 native int 加載到計(jì)算堆棧的頂部。
Ldelem.I1    將位于指定數(shù)組索引處的 int8 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelem.I2    將位于指定數(shù)組索引處的 int16 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelem.I4    將位于指定數(shù)組索引處的 int32 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelem.I8    將位于指定數(shù)組索引處的 int64 類型的元素作為 int64 加載到計(jì)算堆棧的頂部。
Ldelem.R4    將位于指定數(shù)組索引處的 float32 類型的元素作為 F 類型(浮點(diǎn)型)加載到計(jì)算堆棧的頂部。
Ldelem.R8    將位于指定數(shù)組索引處的 float64 類型的元素作為 F 類型(浮點(diǎn)型)加載到計(jì)算堆棧的頂部。
Ldelem.Ref    將位于指定數(shù)組索引處的包含對(duì)象引用的元素作為 O 類型(對(duì)象引用)加載到計(jì)算堆棧的頂部。
Ldelem.U1    將位于指定數(shù)組索引處的 unsigned int8 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelem.U2    將位于指定數(shù)組索引處的 unsigned int16 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelem.U4    將位于指定數(shù)組索引處的 unsigned int32 類型的元素作為 int32 加載到計(jì)算堆棧的頂部。
Ldelema    將位于指定數(shù)組索引的數(shù)組元素的地址作為 & 類型(托管指針)加載到計(jì)算堆棧的頂部。
Ldfld    查找對(duì)象中其引用當(dāng)前位于計(jì)算堆棧的字段的值。
Ldflda    查找對(duì)象中其引用當(dāng)前位于計(jì)算堆棧的字段的地址。
Ldftn    將指向?qū)崿F(xiàn)特定方法的本機(jī)代碼的非托管指針(native int 類型)推送到計(jì)算堆棧上。
Ldind.I    將 native int 類型的值作為 native int 間接加載到計(jì)算堆棧上。
Ldind.I1    將 int8 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldind.I2    將 int16 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldind.I4    將 int32 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldind.I8    將 int64 類型的值作為 int64 間接加載到計(jì)算堆棧上。
Ldind.R4    將 float32 類型的值作為 F (float) 類型間接加載到計(jì)算堆棧上。
Ldind.R8    將 float64 類型的值作為 F (float) 類型間接加載到計(jì)算堆棧上。
Ldind.Ref    將對(duì)象引用作為 O(對(duì)象引用)類型間接加載到計(jì)算堆棧上。
Ldind.U1    將 unsigned int8 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldind.U2    將 unsigned int16 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldind.U4    將 unsigned int32 類型的值作為 int32 間接加載到計(jì)算堆棧上。
Ldlen    將從零開始的、一維數(shù)組的元素的數(shù)目推送到計(jì)算堆棧上。
Ldloc    將指定索引處的局部變量加載到計(jì)算堆棧上。
Ldloc.0    將索引 0 處的局部變量加載到計(jì)算堆棧上。
Ldloc.1    將索引 1 處的局部變量加載到計(jì)算堆棧上。
Ldloc.2    將索引 2 處的局部變量加載到計(jì)算堆棧上。
Ldloc.3    將索引 3 處的局部變量加載到計(jì)算堆棧上。
Ldloc.S    將特定索引處的局部變量加載到計(jì)算堆棧上(短格式)。
Ldloca    將位于特定索引處的局部變量的地址加載到計(jì)算堆棧上。
Ldloca.S    將位于特定索引處的局部變量的地址加載到計(jì)算堆棧上(短格式)。
Ldnull    將空引用(O 類型)推送到計(jì)算堆棧上。
Ldobj    將地址指向的值類型對(duì)象復(fù)制到計(jì)算堆棧的頂部。
Ldsfld    將靜態(tài)字段的值推送到計(jì)算堆棧上。
Ldsflda    將靜態(tài)字段的地址推送到計(jì)算堆棧上。
Ldstr    推送對(duì)元數(shù)據(jù)中存儲(chǔ)的字符串的新對(duì)象引用。
Ldtoken    將元數(shù)據(jù)標(biāo)記轉(zhuǎn)換為其運(yùn)行時(shí)表示形式,并將其推送到計(jì)算堆棧上。
Ldvirtftn    將指向?qū)崿F(xiàn)與指定對(duì)象關(guān)聯(lián)的特定虛方法的本機(jī)代碼的非托管指針(native int 類型)推送到計(jì)算堆棧上。
Leave    退出受保護(hù)的代碼區(qū)域,無條件將控制轉(zhuǎn)移到特定目標(biāo)指令。
Leave.S    退出受保護(hù)的代碼區(qū)域,無條件將控制轉(zhuǎn)移到目標(biāo)指令(縮寫形式)。
Localloc    從本地動(dòng)態(tài)內(nèi)存池分配特定數(shù)目的字節(jié)并將第一個(gè)分配的字節(jié)的地址(瞬態(tài)指針,* 類型)推送到計(jì)算堆棧上。
Mkrefany    將對(duì)特定類型實(shí)例的類型化引用推送到計(jì)算堆棧上。
Mul    將兩個(gè)值相乘并將結(jié)果推送到計(jì)算堆棧上。
Mul.Ovf    將兩個(gè)整數(shù)值相乘,執(zhí)行溢出檢查,并將結(jié)果推送到計(jì)算堆棧上。
Mul.Ovf.Un    將兩個(gè)無符號(hào)整數(shù)值相乘,執(zhí)行溢出檢查,并將結(jié)果推送到計(jì)算堆棧上。
Neg    對(duì)一個(gè)值執(zhí)行求反并將結(jié)果推送到計(jì)算堆棧上。
Newarr    將對(duì)新的從零開始的一維數(shù)組(其元素屬于特定類型)的對(duì)象引用推送到計(jì)算堆棧上。
Newobj    創(chuàng)建一個(gè)值類型的新對(duì)象或新實(shí)例,并將對(duì)象引用(O 類型)推送到計(jì)算堆棧上。
Nop    如果修補(bǔ)操作碼,則填充空間。盡管可能消耗處理周期,但未執(zhí)行任何有意義的操作。
Not    計(jì)算堆棧頂部整數(shù)值的按位求補(bǔ)并將結(jié)果作為相同的類型推送到計(jì)算堆棧上。
Or    計(jì)算位于堆棧頂部的兩個(gè)整數(shù)值的按位求補(bǔ)并將結(jié)果推送到計(jì)算堆棧上。
Pop    移除當(dāng)前位于計(jì)算堆棧頂部的值。
Prefix1    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix2    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix3    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix4    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix5    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix6    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefix7    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Prefixref    基礎(chǔ)結(jié)構(gòu)。此指令為保留指令。
Readonly    指定后面的數(shù)組地址操作在運(yùn)行時(shí)不執(zhí)行類型檢查,并且返回可變性受限的托管指針。
Refanytype    檢索嵌入在類型化引用內(nèi)的類型標(biāo)記。
Refanyval    檢索嵌入在類型化引用內(nèi)的地址(& 類型)。
Rem    將兩個(gè)值相除并將余數(shù)推送到計(jì)算堆棧上。
Rem.Un    將兩個(gè)無符號(hào)值相除并將余數(shù)推送到計(jì)算堆棧上。
Ret    從當(dāng)前方法返回,并將返回值(如果存在)從調(diào)用方的計(jì)算堆棧推送到被調(diào)用方的計(jì)算堆棧上。
Rethrow    再次引發(fā)當(dāng)前異常。
Shl    將整數(shù)值左移(用零填充)指定的位數(shù),并將結(jié)果推送到計(jì)算堆棧上。
Shr    將整數(shù)值右移(保留符號(hào))指定的位數(shù),并將結(jié)果推送到計(jì)算堆棧上。
Shr.Un    將無符號(hào)整數(shù)值右移(用零填充)指定的位數(shù),并將結(jié)果推送到計(jì)算堆棧上。
Sizeof    將提供的值類型的大小(以字節(jié)為單位)推送到計(jì)算堆棧上。
Starg    將位于計(jì)算堆棧頂部的值存儲(chǔ)到位于指定索引的參數(shù)槽中。
Starg.S    將位于計(jì)算堆棧頂部的值存儲(chǔ)在參數(shù)槽中的指定索引處(短格式)。
Stelem    用計(jì)算堆棧中的值替換給定索引處的數(shù)組元素,其類型在指令中指定。
Stelem.I    用計(jì)算堆棧上的 native int 值替換給定索引處的數(shù)組元素。
Stelem.I1    用計(jì)算堆棧上的 int8 值替換給定索引處的數(shù)組元素。
Stelem.I2    用計(jì)算堆棧上的 int16 值替換給定索引處的數(shù)組元素。
Stelem.I4    用計(jì)算堆棧上的 int32 值替換給定索引處的數(shù)組元素。
Stelem.I8    用計(jì)算堆棧上的 int64 值替換給定索引處的數(shù)組元素。
Stelem.R4    用計(jì)算堆棧上的 float32 值替換給定索引處的數(shù)組元素。
Stelem.R8    用計(jì)算堆棧上的 float64 值替換給定索引處的數(shù)組元素。
Stelem.Ref    用計(jì)算堆棧上的對(duì)象 ref 值(O 類型)替換給定索引處的數(shù)組元素。
Stfld    用新值替換在對(duì)象引用或指針的字段中存儲(chǔ)的值。
Stind.I    在所提供的地址存儲(chǔ) native int 類型的值。
Stind.I1    在所提供的地址存儲(chǔ) int8 類型的值。
Stind.I2    在所提供的地址存儲(chǔ) int16 類型的值。
Stind.I4    在所提供的地址存儲(chǔ) int32 類型的值。
Stind.I8    在所提供的地址存儲(chǔ) int64 類型的值。
Stind.R4    在所提供的地址存儲(chǔ) float32 類型的值。
Stind.R8    在所提供的地址存儲(chǔ) float64 類型的值。
Stind.Ref    存儲(chǔ)所提供地址處的對(duì)象引用值。
Stloc    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)到指定索引處的局部變量列表中。
Stloc.0    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)到索引 0 處的局部變量列表中。
Stloc.1    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)到索引 1 處的局部變量列表中。
Stloc.2    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)到索引 2 處的局部變量列表中。
Stloc.3    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)到索引 3 處的局部變量列表中。
Stloc.S    從計(jì)算堆棧的頂部彈出當(dāng)前值并將其存儲(chǔ)在局部變量列表中的 index 處(短格式)。
Stobj    將指定類型的值從計(jì)算堆棧復(fù)制到所提供的內(nèi)存地址中。
Stsfld    用來自計(jì)算堆棧的值替換靜態(tài)字段的值。
Sub    從其他值中減去一個(gè)值并將結(jié)果推送到計(jì)算堆棧上。
Sub.Ovf    從另一值中減去一個(gè)整數(shù)值,執(zhí)行溢出檢查,并且將結(jié)果推送到計(jì)算堆棧上。
Sub.Ovf.Un    從另一值中減去一個(gè)無符號(hào)整數(shù)值,執(zhí)行溢出檢查,并且將結(jié)果推送到計(jì)算堆棧上。
Switch    實(shí)現(xiàn)跳轉(zhuǎn)表。
Tailcall    執(zhí)行后綴的方法調(diào)用指令,以便在執(zhí)行實(shí)際調(diào)用指令前移除當(dāng)前方法的堆棧幀。
Throw    引發(fā)當(dāng)前位于計(jì)算堆棧上的異常對(duì)象。
Unaligned    指示當(dāng)前位于計(jì)算堆棧上的地址可能沒有與緊接的 ldind、stind、ldfld、stfld、ldobj、stobj、initblk 或 cpblk 指令的自然大小對(duì)齊。
Unbox    將值類型的已裝箱的表示形式轉(zhuǎn)換為其未裝箱的形式。
Unbox.Any    將指令中指定類型的已裝箱的表示形式轉(zhuǎn)換成未裝箱形式。
Volatile    指定當(dāng)前位于計(jì)算堆棧頂部的地址可以是易失的,并且讀取該位置的結(jié)果不能被緩存,或者對(duì)該地址的多個(gè)存儲(chǔ)區(qū)不能被取消。
Xor    計(jì)算位于計(jì)算堆棧頂部的兩個(gè)值的按位異或,并且將結(jié)果推送到計(jì)算堆棧上。

View Code

通過雙擊一個(gè)對(duì)象來查看其 IL 代碼,下面將以之前代碼中的 SayNum 方法為例進(jìn)行分析:

.method public hidebysig instance void  SayNum(int32 num) cil managed
{
  // Code size       24 (0x18)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "the num is {0}"
  IL_0006:  ldarg.1
  IL_0007:  box        [mscorlib]System.Int32
  IL_000c:  call       string [mscorlib]System.String::Format(string,
                                                              object)
  IL_0011:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0016:  nop
  IL_0017:  ret
} // end of method Person::SayNum

View Code

以上 IL 代碼中會(huì)用到的指令有:

1)nop:無操作

2)ret:從當(dāng)前方法返回,并將返回值(如果存在)從調(diào)用方的計(jì)算堆棧推送到被調(diào)用方的計(jì)算堆棧上。

3)call:調(diào)用由傳遞的方法說明符指示的方法。

4)box:將值類轉(zhuǎn)換為對(duì)象引用,就是裝箱,同理可以知道拆箱unbox

5)ldstr: 推送對(duì)元數(shù)據(jù)中存儲(chǔ)的字符串的新對(duì)象引用

6)ldarg.1:將索引為 1 的參數(shù)加載到計(jì)算堆棧上

對(duì) IL 代碼添加注釋后如下:

.method public hidebysig instance void  SayNum(int32 num) cil managed
{
  // Code size       24 (0x18) // 代碼大小
  .maxstack  8 // 計(jì)算出計(jì)算堆棧能存幾個(gè)值
  IL_0000:  nop // 無操作
  IL_0001:  ldstr      "the num is {0}" // 推送對(duì)元數(shù)據(jù)中存儲(chǔ)的字符串的新對(duì)象引用
  IL_0006:  ldarg.1 // 將索引為 1 的參數(shù)加載到計(jì)算堆棧上
  IL_0007:  box        [mscorlib]System.Int32 // 裝箱
  IL_000c:  call       string [mscorlib]System.String::Format(string,object) // 調(diào)用內(nèi)部方法
  IL_0011:  call       void [mscorlib]System.Console::WriteLine(string) // 調(diào)用WriteLine
  IL_0016:  nop // 無操作
  IL_0017:  ret // return
} // end of method Person::SayNum

View Code

總結(jié)

以上是生活随笔為你收集整理的通用中间语言(CIL)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。