- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我使用 ILGenerator 生成一些 IL,这是我的代码:
DynamicMethod method = new DynamicMethod("test", null, Type.EmptyTypes);
ILGenerator gen = method.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Ldc_I4_S, 100);
这生成了这个 IL:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldc.i4.s 100
IL_0004: nop
IL_0005: nop
IL_0006: nop
(我从名为 ILStream 的 VS Virtulizer 获取 IL 代码)
nops 代码从哪里来?有什么办法可以摆脱它们吗?我试图模仿一些 c# 代码,但它没有 3 个 nop。
最佳答案
你的方向是正确的,可以摆脱“nop”:
当您为 Emit 调用提供额外的参数时,请始终确保在 MSDN 上检查正确的参数类型。
对于 OpCodes.Ldc_I4_S,MSDN 指出:
ldc.i4.s is a more efficient encoding for pushing the integers from -128 to 127 onto the >evaluation stack.
以下 Emit 方法重载可以使用 ldc.i4.s 操作码:
ILGenerator.Emit(OpCode, byte)
所以你的代码的第二部分在运行时会有不可预测的结果(除了那些讨厌的 nop 之外),因为你试图在堆栈上加载一个“int8”,但提供一个“int32”或“short”值(value):
else if (IsBetween(value, short.MinValue, short.MaxValue))
{
gen.Emit(OpCodes.Ldc_I4_S, (short)value);
}
else
{
gen.Emit(OpCodes.Ldc_I4_S, value);
}
如果您想将 int32/short(或任何比字节更大的值)正确地加载到堆栈上,您应该使用 Ldc_I4 而不是 Ldc_I4_S。 因此您的代码应该如下所示,而不是上面的示例:
else
{
gen.Emit(OpCodes.Ldc_I4, value);
}
这是一个大胆的猜测,但生成的三个 nop 可能与此有关使用来自 int32 的额外字节
希望对您有所帮助...
关于c# ILGenerator nop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1498162/
给出以下代码: using System; using System.Reflection.Emit; using System.Diagnostics; using System.Reflectio
我正在尝试构造一个泛型类型的实例并在该实例上调用一个方法。然后返回方法的结果。 var genericType = typeof(GenericType<>).MakeGenericType(type
我想得到这个: .property instance class [WorldTool.Core]WorldTool.IInputPort SomePort { .get instance c
我正在尝试使用 DynamicMethod 并尝试使用 IL 来创建一些对象。我想创建以下非常基本的对象: new Queue(new List{100}); 我已经使用 ILDASM 查看生成此代码
我正在使用 System.Reflection.Emit 为类型生成包装器。在某一时刻,原始对象可能会在访问时抛出错误 (FaultException),并且该错误应该被我的 try { } catc
Food obj = ...; ILGenerator gen = (...).GetILGenerator(); gen.Emit( ?? obj ?? ); // replace this gen
我使用 ILGenerator 生成一些 IL,这是我的代码: DynamicMethod method = new DynamicMethod("test", null, Type.EmptyTyp
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我必须将一个对象的实例传递给一个函数,所以显然所有要作为参数的信息都将加载到评估堆栈中这是我正在寻找的代码 someClass SomeObject = new someClass(); il.Emi
使用 Ildasm 我得到了这个: .method public hidebysig virtual instance string Mymethod() cil manage
我已经编写了一些函数来使用 ILGenerator 创建一个 exe 文件。我想要的是向用户展示在不使用外部工具(如 ILDasm 或 Reflector)的情况下生成的 IL 语言。 在我的程序执行
考虑为我自己的语言制作编译器,我尝试使用 Reflection.Emit 框架生成一些 MSIL 代码。当我声明局部变量时使用 int 时它工作正常。但是,当我想声明一个尚未编译的类型的局部变量时,我
我正在使用 ILGenerator.Emit 生成动态类型。我正在生成一个方法主体,它将方法参数的类型存储在一个数组中。为了实际将元素存储在数组中,我循环遍历给定方法的参数并构建必要的 IL 来存储元
如何使用 ILGenerator 设置 .maxstack 指令? 例如,典型的 setter 方法的 .maxstack 为 2: .maxstack 2 // The evalua
我如何使用 ILGenerator.Emit(不是 LambdaExpression.Compile?因为我正在尝试寻找性能更高的解决方案)动态创建具有未知 MethodInfo 的委托(delega
我有一些代码使用 IlGenerator.Emit 使用数据读取器创建和填充通用对象。它工作得很好,但是我需要扩展它以在数据库字段名称包含下划线时填充简单的子对象。 例如,名为“Address_Lin
基本上,我试图将字节数组中的数据反序列化为对象。我正在尝试使用 UTF8 编码的 GetString 方法来读取字符串。这是我的部分代码: var mm = new DynamicMethod("ge
我正在使用 System.Reflection.Emit,有时我想从 MethodBuilder 创建一个委托(delegate): MethodBuilder fooBuilder = create
我正在尝试通过在运行时发出 IL 来编译 DynamicMethod。我希望它执行以下操作: array.OrderByDesc( /* Select Field/Property Expressio
我添加到 ILGenerator 字符串 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldfld, readField); 和 ilGen.Emit
我是一名优秀的程序员,十分优秀!