简体   繁体   中英

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:

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. What's confusing me is the line IL_0003 . Its saying that it should branch to line IL_0010 if its true. In my C# code though, I am using an && to compare two expressions before my program flow should jump to the next 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. 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.

brtrue.s transfers control to the given target if the value on the stack is non-zero.

so, In your IL code IL_0003 is tranfers control to IL_0010 . means (val % 3 == 0) condition return 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

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:  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

This blok load arguments data from Stack, before begin comparing

So it's normal to jump to this section of loading data

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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