.NET CIL操纵评估堆栈

我有这个CIL代码序列,我通过使用Mono.Cecil注入。 但是,修改后的.NET C#应用程序将无法运行。

目标:从堆栈中手动加载和弹出值以在Console.WriteLine显示

  for (int i = 0; i < 3; i++) { int z = some value popped manually from stack; Console.WriteLine(z); } 

这是我修改的简单main()程序:

 .method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 5 .locals init ( [0] int32 num, [1] int32 num2) L_0000: ldc.i4.6 //manually push value 6 to stack L_0001: ldc.i4.5 //manually push value 5 to stack L_0002: ldc.i4.4 //manually push value 4 to stack L_0003: ldc.i4.0 //push int i initial value 0 to stack L_0004: stloc.0 //pop and store to int i variable to variable num L_0005: br.s L_0013 L_0007: nop L_0008: stloc.1 //pop the pushed values 6,5 and 4 to variable num2 L_0009: ldloc.1 //load value of num2 to stack L_000a: call void [mscorlib]System.Console::WriteLine(int32) //pop value of num2 and print L_000f: ldloc.0 //load previous value in variable num to stack L_0010: ldc.i4.1 //load incremental value 1 to stack L_0011: add //pop and add the top 2 values, result is pushed to stack L_0012: stloc.0 //store the new result to variable num. (int i) L_0013: ldloc.0 //push int i variable value to stack L_0014: ldc.i4.3 //push value 3 to stack as number of times to loop L_0015: blt.s L_0007 //branch less than (pop and cmp the top 2 values in stack) L_0017: ret } 

但是,上面的代码无法运行。 我尝试将blt.s更改为cltbr_true.s但它也不起作用。 有谁知道是否有可能实现我的目标? 谢谢。

编辑:根据ECMA-335,III.1.7.5,可能存在向后分支约束。 不确定是否是这种情况。

特别是,如果单次通过分析到达指令,则将其称为位置X,紧跟在无条件分支之后,并且其中X不是先前分支指令的目标,那么X处的评估堆栈的状态, ,不能从现有信息中推导出来。 在这种情况下,CLI要求X处的评估堆栈为空。

您的IL-Code看起来没问题,但我认为CLR可能无法在方法完成后检查堆栈是否已损坏。 当某些东西被推入堆栈时,CLR会检查该值是否也从堆栈中弹出。

因此,如果将3个值压入堆栈,则CLR可能无法检查循环是否正在运行三次,因此当方法返回时,CLR不知道堆栈中是否仍有值。