What exactly does the == operator do?

So, I looked at ILDASM, checking the .exe file, which looks like this:

int a = 2; Int32 b = 1; if(b == 1) { } 

Now the CIL code looks like this:

 IL_0005: ldloc.1 IL_0006: ldc.i4.1 IL_0007: ceq IL_0009: ldc.i4.0 IL_000a: ceq IL_000c: stloc.2 

I understand that the first b is loaded (which is stored in [1]), then a constant with a value of 1, and then compared. I do not understand why another constant with a value of 0 is loaded and compared until the comparison result is saved.
Since the first comparison should already produce a true value, checking if this value is 0 inverts the result, right?
Now my question is: why is it upside down? I assume this has something to do with the == operator I used, and my theory is that it returns the difference. If this difference is 0, the values ​​will be the same, so the result should be true. But 0 means false, so you need to flip it.
I just can't find anything about this topic, just about operators like == ~ or the like. I hope you can enlighten me :)

Best wishes

Wilsu

PS: This is the full code:

 .method private hidebysig instance void Form1_Load(object sender, class [mscorlib] System.EventArgs e) cil managed { // Code size 19 (0x13) .maxstack 2 .locals init ([0] int32 a, [1] int32 b, [2] bool CS$4$0000) IL_0000: nop IL_0001: ldc.i4.2 IL_0002: stloc.0 IL_0003: ldc.i4.1 IL_0004: stloc.1 IL_0005: ldloc.1 IL_0006: ldc.i4.1 IL_0007: ceq IL_0009: ldc.i4.0 IL_000a: ceq IL_000c: stloc.2 IL_000d: ldloc.2 IL_000e: brtrue.s IL_0012 IL_0010: nop IL_0011: nop IL_0012: ret } // end of method Form1::Form1_Load 
+5
source share
2 answers

He jumps to the end of the function as far as I can put together.

 void Main() { int a = 2; Int32 b = 1; if(b == 1) { Console.WriteLine("A"); } } 

Gives me:

 IL_0000: nop IL_0001: ldc.i4.2 IL_0002: stloc.0 // a IL_0003: ldc.i4.1 IL_0004: stloc.1 // b IL_0005: ldloc.1 // b IL_0006: ldc.i4.1 IL_0007: ceq IL_0009: ldc.i4.0 IL_000A: ceq IL_000C: stloc.2 // CS$4$0000 IL_000D: ldloc.2 // CS$4$0000 IL_000E: brtrue.s IL_001D IL_0010: nop IL_0011: ldstr "A" IL_0016: call System.Console.WriteLine IL_001B: nop IL_001C: nop IL_001D: ret 

Starting with IL_0005, we have:

Download b .
Download 1 .
ceq (If equal, press 1 , if false push 0 ) - The result here will be 1
Download 0
ceq - The result here will be 0
brtrue.s IL_001D - If the value is nonzero, go to IL_001D (end of function)

Therefore, it is essentially compiled:

 int a = 2; Int32 b = 1; if(!(b == 1)) goto end; Console.WriteLine("A"); :end return; 
+1
source

ceq takes two values ​​from the stack and results in 1 if they are considered equal, and 0 if they are not. However, regardless of whether == in C # leads to ceq , it depends on a lot of things:

  • data types
    • are they primitive?
    • Do they have custom == operators?
    • Are these links?
  • context
    • can it be optimized for something else? (I get a bne.un.s in a similar example, there are also beq* , br* , switch , etc.)
    • Is it possible to completely remove it?
+3
source

Source: https://habr.com/ru/post/1235863/


All Articles