首次见到ldind.i*的实际用法,缘于一个准备偷懒的巧合。
因为项目启用了开发经验不是那么丰富的技术,所以有些内容经验需要进行一些“理论指导/培训和知识迁移”。
公司之前的项目多采用单独字段存储(单机游戏存储在本地)及JsonDotNet(即NewtonJson,弱网游,存档上传服务器)序列化存储的方式,而项目中采用了ProtoBuff的方式,因此很多时候需要根据插件的调整而修改内存加密的“适配”方案,鉴于一贯的偷懒原则,所以很随意大胆的就考虑是否可以直接尝试修改内置的数据类型(eg:int32,在mscorlib.dll中)。。。
直接到引擎安装目录下,找到对应文件并将其拖入我们的小工具ILSpy打开(不同版本的U3D引擎使用的版本可能不同),可以看到如下的命名空间结构:
基本的数据类型就在System下,如图:
分别切成C#及IL的方式查看下源码(以下均以常用的int类型为例,可以直接在线看源码: https://referencesource.microsoft.com/#mscorlib/system/int32.cs):
这里选取了CompareTo函数为例,对应的IL代码为:
看到这里第一反应是奇怪,这就不得不先提一下class/struct类型的内存结构及ldind.i*的解释:
通过msdn(OpCodes.Ldind_I*系列字段,https://msdn.microsoft.com/zh-cn/library/azure/system.reflection.emit.opcodes.ldind_i(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb)及wiki,具体释义及过程如图:
而作为int类型的第一个字段m_value,该地段的地址即为int结构的地址,可以参见下面的小示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; class Program { static unsafe void Main(string[] args) { StructTest tStructTest = new StructTest(); tStructTest.A = 100; Console.WriteLine("0x{0:x}", (int)&tStructTest); Console.WriteLine("0x{0:x}", (int)&tStructTest.A); } } public struct StructTest { public int A; };
因此才会出现在ILSpy中的反编译结果显示为直接将this与参数value进行比较的情形。
分析到这里就告一段落,接下来的偷懒可以尝试直接下载源码重新编译mscorlib.dll的形式进行测试,亦或者使用mono.cecil对其进行静态织入,总之省事就好了。
之后有时间再来进行底层基础类型的修改测试了。