== 运算符到底做了什么?

What exactly does the == operator do?

所以我查看了 ILDASM,检查了一个如下所示的 .exe:

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

}

现在,CIL 代码如下所示:

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

我知道首先加载 b(存储在 [1]),然后加载一个值为 1 的常量,然后比较它们。我不明白的是为什么在存储比较结果之前加载并比较另一个值为 0 的常量。
由于第一次比较应该已经产生真值,检查该值是否为 0 会反转结果,对吗?
我现在的问题是:为什么它是倒置的? 我假设它与我使用的 == 运算符有关,我的理论是它 returns 不同。如果此差异为 0,则值相同,因此结果应为 true。但是0代表false,所以需要取反
我似乎找不到关于这个主题的任何信息,只是关于 ==~ 之类的运算符的信息。 希望大家多多指教:)

此致

威尔苏

PS:这是完整代码:

.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[=12=]00)
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

据我所知,它正在跳转到函数的末尾。

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

给我:

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[=11=]00
IL_000D:  ldloc.2     // CS[=11=]00
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         

从 IL_0005 开始,我们有:

加载b.
加载 1.
ceq(如果相等,则推送 1,如果不相等,则推送 0)- 这里的结果将是 1
加载 0
ceq - 这里的结果将是 0
brtrue.s IL_001D - 如果值为非零,则跳转到 IL_001D(函数结束)

所以它基本上编译成这样:

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

ceq 从堆栈中获取两个值,如果它们相等,则结果为 1,否则为 0。但是,C# 中的 == 是否会导致 ceq 取决于很多因素:

  • 数据类型
    • 它们是原始动物吗?
    • 他们有自定义 == 运算符吗?
    • 它们是参考文献吗?
  • 上下文
    • 可以针对其他内容进行优化吗? (我在类似的例子中得到 bne.un.s;还有 beq*br*switch 等)
    • 能彻底去除吗?