gpt4 book ai didi

c# ILGenerator nop?

转载 作者:太空狗 更新时间:2023-10-29 21:11:23 29 4
gpt4 key购买 nike

我使用 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com