林产生一些IL与这里的ILGenerator是我的代码:
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
(我从VS Virtulizer名为ILStream获得IL代码)
从哪里做的NOP代码? 有没有什么办法来摆脱他们的? 我试着去模仿一些C#代码,它不会有3个空指令。
你是在正确的方向,以摆脱“NOP” S的:
当您提供一个额外的参数给发送调用,总是一定要检查MSDN上的适当的参数类型。
对于OpCodes.Ldc_I4_S,MSDN指出:
ldc.i4.s为从-128推动整数127到>计算堆栈的更有效的编码。
下面的Emit方法重载可以使用ldc.i4.s操作码:
ILGenerator.Emit(操作码,字节)
所以,你的代码的第二部分将在运行时无法预料的结果(除了那些讨厌的NOP的),因为你试图加载在堆栈上“INT8”,而是提供了一个“INT32”或“短”值:
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 /短(更大的幅度比字节或任何)压入堆栈,您应该使用Ldc_I4代替Ldc_I4_S。 所以,你的代码应该是这样的,而不是上面的示例:
else
{
gen.Emit(OpCodes.Ldc_I4, value);
}
这是一种野生的猜测,但生成的三个NOP的大概有东西从你的INT32做额外的字节
希望可以帮助...
我通过铸造的int值解决了这个问题:
码:
private static bool IsBetween(int value, int min, int max)
{
return (value >= min && value <= max);
}
private static void WriteInt(ILGenerator gen, int value)
{
gen.Emit(OpCodes.Ldarg_1);
if (IsBetween(value, sbyte.MinValue, sbyte.MaxValue))
{
gen.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
}
else if (IsBetween(value, byte.MinValue, byte.MaxValue))
{
gen.Emit(OpCodes.Ldc_I4_S, (byte)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);
}
}