简体   繁体   English

分析从C#生成的MSIL代码

[英]Analyzing MSIL code generated from C#

I have the following function: 我有以下功能:

public string MyPhrase(int val)
{
    if ((val %3 == 0) && (val % 6 == 0))
        return "Fizz Bang";
    if (val % 3 == 0)
        return "Fizz";
    if (val % 6 == 0)
        return "Bang";
    return "";
}

After compiling this and viewing it with IlDasm, I get this output: 编译并使用IlDasm对其进行查看后,我得到以下输出:

IL_0000:  ldarg.1
IL_0001:  ldc.i4.3
IL_0002:  rem
IL_0003:  brtrue.s   IL_0010

IL_0005:  ldarg.1
IL_0006:  ldc.i4.6
IL_0007:  rem
IL_0008:  brtrue.s   IL_0010

IL_000a:  ldstr      "Fizz Bang"
IL_000f:  ret

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
IL_0012:  rem
IL_0013:  brtrue.s   IL_001b

IL_0015:  ldstr      "Fizz"
IL_001a:  ret

IL_001b:  ldarg.1
IL_001c:  ldc.i4.6
IL_001d:  rem
IL_001e:  brtrue.s   IL_0026

IL_0020:  ldstr      "Bang"
IL_0025:  ret

IL_0026:  ldstr      ""
IL_002b:  ret

From looking at this page , brtrue will branch if true. 通过查看此页面brtrue如果为true,将分支。 What's confusing me is the line IL_0003 . 使我感到困惑的是IL_0003行。 Its saying that it should branch to line IL_0010 if its true. 俗话说,如果为真,则应分支到第IL_0010行。 In my C# code though, I am using an && to compare two expressions before my program flow should jump to the next if . 但是在我的C#代码中,我使用&&比较两个表达式,然后程序流应跳至下一个if It seems backwards. 似乎倒退了。 From the MSIL code posted, it seems like its checking to see if my operation is true and if it is, its jumping to my next if block, which would be logically wrong. 从发布的MSIL代码中,似乎要检查我的操作是否正确,如果是,则跳转到下一个if块,这在逻辑上是错误的。 Can someone explain what I'm missing? 有人可以解释我所缺少的吗?

This is a side-effect of short circuit evaluation for the && operator. 这是&&运算符的短路评估的副作用。 Which promises that the right-hand expression of the operator does not get evaluated if the left-hand side is false. 这保证如果左侧为假,则不会对运算符的右侧表达式求值。 So you see it skip the val % 6 == 0 expression and the return "Fizz Bang" statement if the REM opcode returns a non-zero result. 因此,您将看到它跳过val%6 == 0表达式,并且在REM操作码返回非零结果时返回“ Fizz Bang”语句。

brtrue.s transfers control to the given target if the value on the stack is non-zero. 如果堆栈上的值不为零,则brtrue.s会将控制转移到给定的目标。

so, In your IL code IL_0003 is tranfers control to IL_0010 . 因此,在您的IL代码IL_0003控制权转移到IL_0010 means (val % 3 == 0) condition return false. 表示(val%3 == 0)条件返回false。 you used && in first if condition if ((val %3 == 0) && (val % 6 == 0)) so, on first condition (val % 3 == 0) return false, second condition will not check 您在第一个条件中使用&& if条件if ((val %3 == 0) && (val % 6 == 0))如此,在第一个条件(val % 3 == 0)返回false时,第二个条件将不检查

IL_0005:  ldarg.1
IL_0006:  ldc.i4.6
IL_0007:  rem
IL_0008:  brtrue.s   IL_0010

and control transfer to IL_0010 并将控制权转移到IL_0010

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
IL_0012:  rem
IL_0013:  brtrue.s   IL_001b

check out this for more information: http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx 请查看此以获取更多信息: http : //weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx

This blok load arguments data from Stack, before begin comparing 开始比较之前,此方法从Stack加载参数数据

So it's normal to jump to this section of loading data 因此,跳转到此部分加载数据是正常的

IL_0010:  ldarg.1
IL_0011:  ldc.i4.3
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM