使用Br_S OpCode指向使用Reflection.Emit.Label的下一条指令

Sea*_*man 1 c# reflection il reflection.emit opcode

我正在尝试解析IL,以发出一种方法。我已经在string []中获得了方法的IL代码,其中每个字符串都是IL指令。我遍历此数组并使用ILGenerator添加OpCodes:

        foreach (string ins in instructions) //string representations of IL          
        {
            string opCode = ins.Split(':').ElementAt(1);

            // other conditions omitted

            if (opCode.Contains("br.s"))
            {
                Label targetInstruction = ilGenerator.DefineLabel();

                ilGenerator.MarkLabel(targetInstruction);

                ilGenerator.Emit(OpCodes.Br_S, targetInstruction); 
            }
Run Code Online (Sandbox Code Playgroud)

这是我需要重现的IL:

Source IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

Target IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0007   // this is wrong -- needs to point to IL_0009
IL_0009: ldloc.0
IL_000a: ret
Run Code Online (Sandbox Code Playgroud)

如您所见,br.s调用指向自身,这当然会导致无限循环。如何获得源代码中的以下说明?这与使用Reflection.Emit.Label有关,但是我不确定它是如何工作的。

编辑通过上面看到的IL就是这种简单方法,

    public string HelloWorld()
    {
            return "Hello, World!";
    }
Run Code Online (Sandbox Code Playgroud)

ang*_*son 5

这段代码:

ilGenerator.MarkLabel(targetInstruction);
ilGenerator.Emit(OpCodes.Br_S, targetInstruction); 
Run Code Online (Sandbox Code Playgroud)

清楚地说出“在此处标记标签”,然后将说明添加到标记标签的位置

如果这不是您想要的,为什么要这样做?

MarkLabel将当前位置标记为标签的目标,这意味着您输出的下一条指令的位置。

在这种情况下,要获得“所需”,只需将这两行颠倒,在标记标签之前输出分支指令。

因为我不明白该分支指令的要点,所以在引号中加上了“您想要什么”。机器会很乐意自己全部“移动”到下一条指令,无需为此添加“分支到下一条指令”指令。