Icemanind
Icemanind

Reputation: 48736

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?

Upvotes: 2

Views: 574

Answers (3)

Jignesh Thakker
Jignesh Thakker

Reputation: 3698

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

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 942197

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.

Upvotes: 4

Aghilas Yakoub
Aghilas Yakoub

Reputation: 29000

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

Upvotes: 0

Related Questions