1、程序执行时,除了顺序执行外,任何程序设计语言,都有条件语句、循环语句、无条件转移语句。而条件语句,几乎每个过程都离不开。
在高级程序编程语言中,使用特定的关键字,编写条件语句是很方便的,如 if语句、if-else、if-else if语句、switch语句等等。
但微软中间语句(MSIL)无特定的条件语句,要实现条件转移,必须定义Label,自己以比较语句、条件转移语句组合来实现。
2、分析条件语句
看下面的C#示例:
分析一下,要用MSIL实现上述很简单的例子:
a)、比较 i 与 j 是否相等;
b)、如不相等,则转移到下一个比较(既 e 处,以执行下一个else if),这里是第一次转移,条件转移,需要一个Label;
c)、如相等,则顺序执行本 if 块内代码;
d)、本代码块执行完毕,则转移到此 if-else if-else 条件语句之后,既j,此是第二个转移,无条件转移,需要第二个Label;
e)、比较 i 是否小于 j;
f)、如不小于,则转移到i处,以执行下一个 else,这里是第三个转移,条件转移,需要第三个Label;
g)、小于,则顺序执行;
h)、小于后的代码块执行完毕,转移到最后,既j;
i)、此时开始执行 i>j的代码;
j)、所有判断结束;
k)、将变量ret加载到栈,并返回。
3、相应的 MSIL代码:
. method private hidebysig static string CompareResult (int32 i, int32 j ) cil managed
{
. maxstack 2
. locals init (
[0] string ret,
[1] string CS$1$0000,
[2] bool CS$4$0001)
L_0000: nop
L_0001: ldstr "/u6bd4/u8f83/u7ed3/u679c/uff1a"
L_0006: stloc.0
L_0007: ldarg.0
L_0008: ldarg.1
L_0009: ceq
L_000b: ldc.i4.0
L_000c: ceq
L_000e: stloc.2
L_000f: ldloc.2
L_0010: brtrue.s L_0020
L_0012: ldloc.0
L_0013: ldstr "/u76f8/u7b49"
L_0018: call string [mscorlib ]System.String::Concat (string, string )
L_001d: stloc.0
L_001e: br.s L_0045
L_0020: ldarg.0
L_0021: ldarg.1
L_0022: clt
L_0024: ldc.i4.0
L_0025: ceq
L_0027: stloc.2
L_0028: ldloc.2
L_0029: brtrue.s L_0039
L_002b: ldloc.0
L_002c: ldstr "i < j"
L_0031: call string [mscorlib ]System.String::Concat (string, string )
L_0036: stloc.0
L_0037: br.s L_0045
L_0039: ldloc.0
L_003a: ldstr "i > j"
L_003f: call string [mscorlib ]System.String::Concat (string, string )
L_0044: stloc.0
L_0045: ldloc.0
L_0046: stloc.1
L_0047: br.s L_0049
L_0049: ldloc.1
L_004a: ret
}
4、在动态方法中使用Label实现转移
要使用Label转移,首先要使用 ILGenerator 类的 DefineLabel 方法定义 Label;
其次,在需要转移到的地方,使用ILGenerator 类的 MakeLabel 方法,将前面定义的Label的地址设定在此处。
下面是使用动态方法的示例代码(此代码是写博客时现写的,未测试)