.NET CIL操作评估堆栈

Ron*_*Ron 5 .net c# cil mono.cecil

我有这个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);
        }
Run Code Online (Sandbox Code Playgroud)

这是我修改的简单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 
}
Run Code Online (Sandbox Code Playgroud)

但是,上面的代码无法运行.我尝试过更改blt.sclt,br_true.s但它也无效.有谁知道是否有可能实现我的目标?谢谢.

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

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

Fel*_* K. 2

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

因此,如果将 3 个值压入堆栈,CLR 可能无法检查循环是否运行了 3 次,因此 CLR 不知道方法返回时堆栈上是否还有值。