【发布时间】:2012-10-07 05:57:15
【问题描述】:
我有通过使用Mono.Cecil 注入的这个CIL 代码序列。但是,修改后的 .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 更改为clt 和br_true.s,但它也不起作用。有谁知道是否有可能实现我的目标?谢谢。
编辑: 根据 ECMA-335, III.1.7.5,可能存在后向分支约束。不知道是不是这样。
特别是,如果单遍分析到达一条指令,称为位置 X,那 紧跟在无条件分支之后,并且 X 不是先前分支的目标 指令,那么 X 处的评估堆栈的状态显然不能从现有的 信息。在这种情况下,CLI 要求 X 处的评估堆栈为空。
【问题讨论】:
-
运行程序时遇到的实际错误是什么?您是否尝试在修改后的程序上运行 peverify?
-
您给验证者方式带来了太多困难,无法检查堆栈是否平衡。它必须深入研究代码以分析循环运行的频率。它不会那样做。
标签: c# .net cil mono.cecil