3

我有问题。这是我的代码:

var method = new DynamicMethod("dummy", null, Type.EmptyTypes);
var g = method.GetILGenerator();
g.DeclareLocal(typeof(int));

Label inequality = g.DefineLabel();
Label equality = g.DefineLabel();
Label end = g.DefineLabel();

g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Ldstr, "string");
g.Emit(OpCodes.Call, typeof(String).GetMethod("op_Equality", new Type[]{typeof(string), typeof(string)}));
g.Emit(OpCodes.Stloc_0);
g.Emit(OpCodes.Ldloc_0);
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(int)}));
g.Emit(OpCodes.Ldloc_0);
g.Emit(OpCodes.Ldc_I4_1);
g.Emit(OpCodes.Ceq);
g.Emit(OpCodes.Brtrue_S, equality);
g.Emit(OpCodes.Brfalse_S, inequality);
g.MarkLabel(inequality);
g.Emit(OpCodes.Ldstr, "Specified strings are different.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(string)}));
g.Emit(OpCodes.Br_S, end);
g.MarkLabel(equality);
g.Emit(OpCodes.Ldstr, "Specified strings are same.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
g.Emit(OpCodes.Br_S, end);
g.MarkLabel(end);
g.Emit(OpCodes.Ret);

var action = (Action)method.CreateDelegate(typeof(Action));
action();

这是我的结果:

1
Specified strings are different.

但是为什么输出错误呢?Ceq 指令将 1 作为 op_Equation 的结果与堆栈顶部的 0 进行比较。1不等于0。那为什么会这样呢?错误在哪里?请帮我。

4

2 回答 2

5

之后g.Emit(OpCodes.Brtrue_S, inequality);,需要手动跳转到“相等”语句。否则无论如何它都会执行下一条指令。因此,您需要在其后插入以下行:

g.Emit(OpCodes.Br_S, equality);

equality此外,当它被声明为下一条指令时,跳转到标签是没有意义的。所以删除它。

所以该部分将如下所示:

g.Emit(OpCodes.Ceq);

g.Emit(OpCodes.Brtrue_S, inequality); // if true goto inequality
g.Emit(OpCodes.Br_S, equality); // else goto equality

g.MarkLabel(inequality);            
g.Emit(OpCodes.Ldstr, "Specified strings are different.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(string)}));
g.Emit(OpCodes.Br_S, end); // goto end

g.MarkLabel(equality);
g.Emit(OpCodes.Ldstr, "Specified strings are same.");
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

g.MarkLabel(end);
g.Emit(OpCodes.Ret);
于 2012-06-21T14:25:47.033 回答
4

你的分支是紧跟在声明后面的标签“不平等”。所以无论你是否分支,这都是将被调用的代码。您应该分支到“平等”标签。

此外,您的行g.Emit(OpCodes.Brfalse_S, equality);是毫无意义的,因为它永远不会到达 - 您在前面的语句中跳过它。一旦逻辑固定,你的“不平等”标签实际上不会在任何地方使用,所以你也可以放弃它。

于 2012-06-21T14:18:15.817 回答