首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mono.Cecil中的固定变量

Mono.Cecil中的固定变量
EN

Stack Overflow用户
提问于 2018-06-15 14:10:24
回答 1查看 450关注 0票数 1

如何使用Mono.Cecil使局部变量固定?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-15 14:52:19

完整的例子:

这是:

代码语言:javascript
复制
public unsafe static void Assign2(byte[] arr) 
{
    fixed (byte* ptr = arr)
        *ptr = 255;

可翻译为:

代码语言:javascript
复制
var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("Test", new Version()), "Test", ModuleKind.Dll);

var module = assembly.MainModule;

var testClassType = new TypeDefinition(
    "TestNamespace",
    "TestClass",
    TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed,
    module.ImportReference(typeof(object)));

module.Types.Add(testClassType);

var assignMethod = new MethodDefinition(
    "Assign",
    MethodAttributes.Public | MethodAttributes.Static,
    module.ImportReference(typeof(void)));

assignMethod.Parameters.Add(new ParameterDefinition("arr", ParameterAttributes.None, module.ImportReference(typeof(byte[]))));

testClassType.Methods.Add(assignMethod);

// Get ILProcessor for the method body
var ilProcessor = assignMethod.Body.GetILProcessor();

ilProcessor.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(byte).MakePointerType())));

// THIS IS WHAT YOU WANT!
// using Mono.Cecil.Rocks or new PinnedType(module.ImportReference(...))
ilProcessor.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(byte[])).MakePinnedType()));

var instrLabelA = ilProcessor.Create(OpCodes.Ldc_I4_0);
var instrLabelB = ilProcessor.Create(OpCodes.Ldloc_1);
var instrLabelC = ilProcessor.Create(OpCodes.Ldloc_0);

ilProcessor.Emit(OpCodes.Ldarg_0);
ilProcessor.Emit(OpCodes.Dup);
ilProcessor.Emit(OpCodes.Stloc_1);
ilProcessor.Emit(OpCodes.Brfalse_S, instrLabelA);

ilProcessor.Emit(OpCodes.Ldloc_1);
ilProcessor.Emit(OpCodes.Ldlen);
ilProcessor.Emit(OpCodes.Conv_I4);
ilProcessor.Emit(OpCodes.Brtrue_S, instrLabelB);

ilProcessor.Append(instrLabelA);
ilProcessor.Emit(OpCodes.Conv_U);
ilProcessor.Emit(OpCodes.Stloc_0);
ilProcessor.Emit(OpCodes.Br_S, instrLabelC);

ilProcessor.Append(instrLabelB);
ilProcessor.Emit(OpCodes.Ldc_I4_0);
ilProcessor.Emit(OpCodes.Ldelema, module.ImportReference(typeof(byte)));
ilProcessor.Emit(OpCodes.Conv_U);
ilProcessor.Emit(OpCodes.Stloc_0);

ilProcessor.Append(instrLabelC);
ilProcessor.Emit(OpCodes.Ldc_I4, 255);
ilProcessor.Emit(OpCodes.Stind_I1);
ilProcessor.Emit(OpCodes.Ldnull);
ilProcessor.Emit(OpCodes.Stloc_1);
ilProcessor.Emit(OpCodes.Ret);

// Save the assembly to disk
assembly.Write(@"test.dll");

IL代码取自SharpLab

你想要的是:

代码语言:javascript
复制
ilProcessor.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(byte[])).MakePinnedType()));

记住要用

代码语言:javascript
复制
using Mono.Cecil.Rocks;

如果不使用Rocks,您可以直接:

代码语言:javascript
复制
ilProcessor.Body.Variables.Add(new VariableDefinition(new PinnedType(module.ImportReference(typeof(byte[])))));

请注意这一点:

代码语言:javascript
复制
public unsafe static void Assign(byte[] arr) 
{
    fixed (byte* ptr = &arr[0])
        *ptr = 255;

应该生成相同的代码,但它不会。

代码语言:javascript
复制
var ilProcessor = assignMethod.Body.GetILProcessor();

// THIS IS WHAT YOU WANT!
// using Mono.Cecil.Rocks or new PinnedType(module.ImportReference(...))
ilProcessor.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(byte)).MakePinnedType()));

ilProcessor.Emit(OpCodes.Ldarg_0);
ilProcessor.Emit(OpCodes.Ldc_I4_0);
ilProcessor.Emit(OpCodes.Ldelema, module.ImportReference(typeof(byte)));
ilProcessor.Emit(OpCodes.Stloc_0);
ilProcessor.Emit(OpCodes.Ldloc_0);
ilProcessor.Emit(OpCodes.Conv_U);
ilProcessor.Emit(OpCodes.Ldc_I4, 255);
ilProcessor.Emit(OpCodes.Stind_I1);

ilProcessor.Emit(OpCodes.Ldc_I4_0);
ilProcessor.Emit(OpCodes.Conv_U);
ilProcessor.Emit(OpCodes.Stloc_0);
ilProcessor.Emit(OpCodes.Ret);

我要说,这是因为在第一种情况下,arr == null || arr.Length == 0必须由代码显式地处理,而在&arr[0]中,它是由.NET (将抛出异常)处理的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50877301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档