---
title: "IL语言学习"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/cil-language-learning/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/02-编程语言与运行时/.NET与CSharp/IL语言学习.md"
content_hash: 2cdb49c9c6c8c69dc218439910a50366b76487596ed0d35182ec2d12be131763
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# IL语言学习

> 创建时间：2020/4/28 16:48

<https://www.cnblogs.com/zery/p/3366175.html>
<https://www.cnblogs.com/zery/p/3376973.html>
<https://blog.csdn.net/u012395622/article/details/46545349>
<https://www.cnblogs.com/yuanyang/p/5422351.html>

操作码文档（包括操作码的用法和特点）：
<https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.emit.opcodes?view=netcore-3.1>

### 概念引入

### 常用操作码

nop:即No Operation 没有任何操作，我们也不用管它，
ldstr.:即Load String 把字符串加压入Evaluation Stack中
stloc.：把Evaluation Stack中的值弹出赋值到Call Stack中的Record Frame中
ldloc.:把Call Stack中的Record Frame中指定位置的值取出(copy)存入 Evaluation Stack中 以上两条指令为相互的操作stloc赋值，ldloc取值
call: 调用指定的方法
ret: 即return 标记返回

#### 三种call的区别

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

**Calli** : MSDN上讲是间接调用指针指向的函数。

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

### ProjectAuditor中分析到的指令

Newobj：创建一个值类型的新对象或新实例，并将对象引用（O 类型）推送到计算堆栈上。

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

Box：将值类转换为对象引用（O 类型）。

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

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

Ret：从当前方法返回，并将返回值（如果存在）从调用方的计算堆栈推送到被调用方的计算堆栈上。
