MSIL学习------从HelloWorld开始
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3889z1y72b288
1.有没有必要学习IL
前段时间突然想搞搞IL语言,于是在博客园中找到了包建强前辈关于IL的文章学习,并且在包前辈博客里看到了09年他与赵劼前辈关于是否有必要学习IL语言的争论,作为一个刚入此行业的新人,没有站在那个高度不敢去评论什么,并且我的引路教员在知道我学IL时就跟我说学习IL还不如学习汇编,IL语言就是一堆指令,谁背的多谁就越精通,我那个教员说的也不错,IL语言就是一堆指令,或许就是站的角度不同,我教员他不止局限于.NET,对C++和汇编都有一定研究,但是现在我还是只局限于.NET体系,学好.NET我感觉对于CIL和CLR一定得有一定的了解。所以我个人的观点是在.NET平台干活的人还是有必要学习学习IL的。现在IL我只是局限于刚学习阶段,所以想写下博客来记录我的学习记录
2.反编译解析HelloWorld
学习IL,首先需要知道其各种指定的含义,所以需要先创建c#语言进行反编译来解析,在这里只需创建一个.CS类并使用命令进行编译与反编译即可,没必要启动宇宙第一IDE(VS)
using System;
namespace HelloWorld
{
class HelloWorld
{
public static void Main(String[] args)
{
System.Console.WriteLine("HelloWorld");
}
}
}
然后需要将.CS文件编译成.EXE文件,在这里需要什么VS的开发者工具(当然应该还有其它方式),
使用SCS语句进行编译
csc HelloWorld.cs
接下来使用ILDASM命令进行反编译为IL文件
ildasm HelloWorld.exe /output=HelloWorld.il
然后就会生成一个.IL文件,这个文件进行HelloWorld.exe反编译后的代码
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C E0 )
.ver :::
}
.assembly HelloWorld
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 4E 6F 6E
6F 6E 6F )
.hash algorithm 0x00008004
.ver :::
}
.module HelloWorld.exe
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003
.corflags 0x00000001
.class private auto ansi beforefieldinit HelloWorld.HelloWorld
extends [mscorlib]System.Object
{
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack
IL_0000: nop
IL_0001: ldstr "HelloWorld"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack
IL_0000: ldarg.
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
}
}
下面来简单学习下这个IL代码
- 可以看到IL中有需要 .assembly .module .class 这样规则的代码,它们是定义信息的伪指令,IL语言不像C#声明类似class时先写修饰符之类,而是首先定义声明的伪指令,先来看看每个伪指令的含义
- .assembly extern [assemblyRefName] {} [可选] 定义一个AssemblyRef(程序集引用)的元数据项,标记了这个程序使用的外部托管应用程序,类似using语句 mscorlib.dll:.NET程序集类库的主程序集。
- .assembly [assemblyName] {} 定义一个程序集的元数据项,如果一个不定义此项,这个文件就不完全是一个应用程序,无法独立指定
- .module [moduleName] 定义一个模块元数据项,标识了当前的模块.
- .class 定义一个TypeDef(类声明)的元数据项
- .method 定义一个MethodDef(方法声明)的元数据项
- 代码中像assembly和module只需要定义好就行,主要需要关注的还是class和method,当然还有field。下面再来介绍下修饰与class和method中的关键字
1.class
- private 访问修饰符,没什么好说的,IL支持6种访问修饰符,C#7.2版本才加入第六种(private protected)
- auto [可选] 定义类的布局风格,auto是自动布局(默认值),只加载程序时可以使用它认为合适的方式进行布局 其它布局风格有sequential(加载程序时保留实例字段的顺序)和explicit(显示指定类型布局)
- ansi [可选] 定义类中字符串与其它非托管代码进行操作时的转换模式, ansi指定了会与”标准“C风格的字节字符串进行转换(默认值),其它有unicode(与UTF-16字符进行转换)和autochar(有底层平台定义的默认字符串转换)
- beforefieldinit [可选] 指静态成员在第一次访问之前被初始化
- extends 继承 也没什么好说的
另外可以看到C#中写的命名空间在IL中直接变成了一个完整类名。这是IL2.0时引入的,
2.method
- public 访问修饰符
- hidebysig 用于隐藏父类的同名方法,类似于C#的new关键字
- specialname 提示编译器和工具这个函数时特殊的, 只存在与构造函数(.ctor)和静态构造函数(.cctor)中
- rtspecialname 告诉运行时这个函数时特殊的 只存在与构造函数(.ctor)和静态构造函数(.cctor)中
- static/instance static 声明这个函数时静态函数 instance:声明这个函数时实例函数
- cil managed 声明这个函数时CIL代码
了解了IL代码整体结构后接下来来看下方法,方法体中通常包含三项:指令,标注了指令的标号和伪指令(在方法体外只有伪指令),在方法中像.entrypoint和.maxstack这类是伪指令,nop,ldstr这属于指定,而IL_0000属于指令标号,指令标号作用是跳转时使用,所以自己写代码时没必要每行都加,只有在需要时加入即可,另外标号不会对伪指令进行标注
在上面C#代码中只定义了一个Main方法,但是在IL文件中却存在两个方法,其中一个方法就是定义的Main方法,而另一个则是C#编辑器加上的默认构造函数(.ctor),从这里可以看出C#的一个知识点(未添加构造函数C#会自动添加一个默认构造函数)
构造函数在此不介绍,只说一下Main方法中的内容,
.entrypoint和.maxstack是两个伪指令,它们的作用分别是.
.entrypoint:将定义此伪指令的方法标识为应用程序入口方法,也就是说在IL中程序入口并不是方法名称为Main的,
.maxstack:栈中存在的最大数量数据,比如Main方法maxstack=8则说明stack中最多容纳8个数据。(IL栈元素不是字节或字,而是槽,当谈论IL栈深度时,指的是放在栈中的项,而不考虑项的大小)
nop 指令代表如果修补操作码,则填充空间,但时是并不执行任何有意义的操作
ldstr 代表加载一个字符串到栈顶
call 方法调用指令,还有另一个方法调用指令为callvirl,在IL中调用方法使用是“::” 而不是C#中的“.”,并且调用前要先声明其返回值类型和参数并不是C#的那种实参变量而是参数的类型,因为IL是一种严格基于栈的语言,方法时会按照参数列表去栈顶进行获取数据,调用完成后如果有返回值也会将返回值放入栈顶
ret 从当前方法返回,并将返回值(如果存在)放入调用方的计算栈中
3.编写一个IL语言的HelloWorld
通过上面的解析可以看出手写一个简单的IL语言的HelloWorld其实挺简单,只需要依葫芦画瓢就可以
.assembly extern mscorlib{ auto}
.assembly HelloWorld_IL{}
.module HelloWorld.HelloWorld_IL.exe
.class private auto ansi HelloWorld.Program extends [mscorlib]System.Object
{
.method public hidebysig rtspecialname specialname instance void .ctor()cil managed
{
ldarg.
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public hidebysig static void MyMain()cil managed
{
.entrypoint
.maxstack
ldstr "HelloWorld"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}
在上面代码中程序集引用中使用的是auto,这是IL2.0版本加入,会自动搜索指定名称程序集
然后在开发者工具使用命令进行编辑
ilasm HelloWorld_IL.il /output=HelloWorld_IL.exe
然后指定就可以看出HelloWorld输出
MSIL学习------从HelloWorld开始的更多相关文章
- AspectJ基础学习之三HelloWorld(转载)
AspectJ基础学习之三HelloWorld(转载) 一.创建项目 我们将project命名为:aspectjDemo.然后我们新建2个package:com.aspectj.demo.aspect ...
- [Cocos2d-x for WP8学习笔记] HelloWorld结构分析
先来看一下目录结构: Assets:游戏资源文件,图片音频等,Resource文件夹也有类似功能 include:用于放置游戏头文件 Shaders:渲染器着色器文件(大雾) cocos2dorig. ...
- [Cocos2d-x for WP8学习笔记] HelloWorld
Cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,使用 C++ 开发,基于OpenGL ES,基于Cocos2d-iphone,支持 WOPhone, iOS 4.1, Android 2. ...
- Emit学习(1) - HelloWorld
之前看过Dapper(使用到了Emit), CYQ.Data(另一种思路,没有使用Emit)类的框架之后, 也想自己做一个小框架玩一下, 不过此时能力太过欠缺, 做不了Cyq.Data或者PDF.Ne ...
- 从零开始学习C#——HelloWorld(一)
从零开始学习C# 老规矩Hello World 您的第一个程序 visual studio 如何使用就不说了 //编程的开始,Hello World! program in C# using Syst ...
- Struts2学习:HelloWorld
项目结构: 1.用IDEA新建一个SpringBoot+Maven的项目 2.新建的项目是没有webapp.WEB-INF.与web.xml文件的,需要在下图中添加: 3.在pom.xml引入stru ...
- (转)Android学习笔记②——HelloWorld的创建已经基本知识
开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程:接下来需要输入应用名称(第一个字母要大写) ...
- Salesforce LWC学习(二) helloWorld程序在VSCode中的实现
上一篇我们简单的描述了一下Salesforce DX的配置以及CLI的简单功能使用,此篇主要简单描述一下LWC如何实现helloWorld以及LWC开发时应该注意的一些规范. 做国内项目的同学直观的感 ...
- JAVA学习2——HelloWorld
Java语言的诞生.版本以及工具:Java的安装开发环境以及环境变量的配置:第一个Java程序--HelloWorld
随机推荐
- 基于open62541的opc ua 服务器开发实现(1)
关于opcua的介绍这里就不多说了,相信大家大都有了一些了解,open62541是一个开源C(C99)的opc-ua实现,开源代码可在官网或github上下载. 话不多说,首先搭建一个opcua服务器 ...
- Docker系列07—Dockerfile 详解
本文收录在容器技术学习系列文章总目录 1.认识Dockerfile 1.1 镜像的生成途径 基于容器制作 dockerfile,docker build 基于容器制作镜像,已经在上篇Docker系列 ...
- java continue break 关键字 详解 区别 用法 标记 标签 使用 示例 联系
本文关键词: java continue break 关键字 详解 区别 用法 标记 标签 使用 示例 联系 跳出循环 带标签的continue和break 嵌套循环 深入continue ...
- Spring基础系列--AOP织入逻辑跟踪
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9619910.html 其实在之前的源码解读里面,关于织入的部分并没有说清楚,那些前置.后 ...
- Linux系统命令行整理
1.pwd 查看当前所在目录 2.cd / 跳往根目录 3.ls 查看当前目录所有子目录或文件 4.ls -l 列出当前目录详细信息 5.ls -lh h=human 人性化列出当前目录详细 ...
- python学习笔记(六)、类
Python与java.c++等都被视为一种面向对象的语言.通过创建自定义类,用于处理各种业务逻辑.面向对象有封装.继承.多态三个特征,这也是面子对象语言的通用特征. 1 封装 封装,是值向外部隐藏内 ...
- Android破解学习之路(十一)—— 关于去更新
根据对话框的文字找到对应的对话框,设置visability 为gone 修改版本号,aptool 搜索http://,找到更新的地址,修改为127.0.0.0 搜索update,upgrade,ver ...
- 【开源】SpringBootNetty聊天室V1.2.0升级版本介绍
前言 SpringBoot!微服务微架构的基础,Netty通信框架的元老级别框架,即之前的SpringBoot与Netty的实现聊天室的功能后已经过了不到一周的时间啦,今天我们更新了项目版本从V1.0 ...
- [python爬虫]Requests-BeautifulSoup-Re库方案--robots协议与Requests库实战
[根据北京理工大学嵩天老师“Python网络爬虫与信息提取”慕课课程编写 慕课链接:https://www.icourse163.org/learn/BIT-1001870001?tid=100223 ...
- 安卓手机如何快速投屏到windows(10/8.1/7)电脑上
前提: 手机和电脑连接的网络必须在同一局域网下. 优势: 手机和电脑不需要下载对应平台的应用,完全使用全系统自带功能. 附加: 以下演示是安卓手机和windows操作系统电脑,并且win10和win1 ...