简谈对ldind.i*的理解

首次见到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对其进行静态织入,总之省事就好了。

之后有时间再来进行底层基础类型的修改测试了。

原文地址:https://www.cnblogs.com/wayland/p/9588587.html