C# 如何使用CIL操作码bne.un vs beq,以及bne.un.s vs beq.s,unsigned vs signed equality

C# 如何使用CIL操作码bne.un vs beq,以及bne.un.s vs beq.s,unsigned vs signed equality,c#,f#,jit,cil,C#,F#,Jit,Cil,我知道beq比bne.un适用于更多的场景(是平等还是不平等),但我想知道是否有任何区别。例如,假设我使用了一个char,并且有x==y,我希望beq.un,但是它不存在,所以我得到bne.un,但是当我使用x!=y,我得到了beq。无符号比较如何导致有符号比较指令?这有关系吗?(提示:可能不是,因为编译器就是这么做的,但为什么会有差异?) 例如: .method public static char test(char x) cil managed { // Code siz

我知道
beq
bne.un
适用于更多的场景(是平等还是不平等),但我想知道是否有任何区别。例如,假设我使用了一个
char
,并且有
x==y
,我希望
beq.un
,但是它不存在,所以我得到
bne.un
,但是当我使用
x!=y
,我得到了beq。无符号比较如何导致有符号比较指令?这有关系吗?(提示:可能不是,因为编译器就是这么做的,但为什么会有差异?)

例如:

  .method public static char  test(char x) cil managed
  {
    // Code size       11 (0xb)
    .maxstack  8
    IL_0000:  ldc.i4.s   97
    IL_0002:  ldarg.0
    IL_0003:  beq.un.s   IL_0008

    IL_0005:  ldc.i4.s   65
    IL_0007:  ret

    IL_0008:  ldc.i4.s   66
    IL_000a:  ret
  }
vs:

示例C#代码:

//这将编译为`bne.un.s`
公共C类{
公共布尔M(字符x){
如果(x='A')
返回true;
返回false;
}
}
//这编译成'beq.s'`
公共C类{
公共布尔M(字符x){
如果(x!=“A”)
返回true;
返回false;
}
}
请参阅sharplab代码:

我很惊讶
==
如何被翻译成(似乎更正确的)
bne.un.s
,与
之间的差异=
被转换为更通用的
beq.s
,而不使用任何无符号指令

编译的JITted机器代码没有显示这会导致不同的程序集(这很好):

但情况总是这样吗?关于这些操作码的文档并不表明,只要结果正确,使用任何一种操作码都是错误的

背景:我在工作时遇到了这种怪癖,对此感到好奇。

这个“未签名”位很奇怪。
beq
的文档没有提到有符号/无符号的值或浮点数,但是
bne.un
的文档明确表示它适用于无符号的值和浮点数。但是,编译器对有符号值和无符号值使用
bne.un

不管怎样,政府都会说:

其效果与执行
ceq
指令,然后执行
brtrue
分支到特定目标指令相同

而政府说:

其效果与执行
ceq
指令,然后执行到特定目标指令的
brfalse
分支相同

因此,我认为可以安全地假设它们彼此完全相反,并且可以在
ceq
可以使用的任何地方使用

ceq
的文档提到浮动,但没有提到有符号/无符号整数


我的怀疑是,
beq.un
之所以如此命名,是因为它在给定的值相等时分支,或者是无序浮点(branch ifequal或un有序浮点)。可能是一个过于热心的文档作者将“un”误解为“unsigned”(正如它对
bxx.un
指令的其余部分所做的那样),这种情况会传播


比较整数时,符号性很重要(即询问一个整数是否大于或小于另一个整数),但不是为了测试它们是否相等:如果两个操作数具有相同的符号性,您只需要检查它们的位模式是否相同。这就是为什么您同时有
ble
ble.un
,但没有
beq.un

您的问题似乎有点困惑:没有指令
beq.un
,并且示例讨论了
beq.s
bne.un.s
(但不是
beq.un
)?@canton7,谢谢你发现了!我会更新的。编辑:完成。看来
beq
bne.un
是完全相反的:没有
beq.un
bne
。如果你阅读文档,它们都完全等同于运行
ceq
,但一个分支是真的,另一个分支是假的。我不确定
bne、 un
与无符号值有关,尤其是编译器也将其用于有符号整数。我怀疑这是因为它比较无序浮点(“如果不相等或无序则分支”)@canton7,这似乎是对我的误解的一个很好的解释。你可以肯定地把它放在一个答案中。这也有道理,不平等中存在无序和从不平等,这是没有道理的。谢谢!谢谢!我看了526页上的“CLI注释标准”。似乎是“无序”“与arg的类型无关,但值是否为
NaN
。因此,它与
beq
完全对应,beq将
NaN==NaN
视为不相等,而
bne.un
NaN!=NaN
视为真。我同意注释“比较时无符号”在这里是多余的。我认为这意味着参数必须是无符号类型,但这不是真的,这是关于语义的。对于无序值,比较操作的注释特别提到了
nan
,只是不适用于分支指令。是的,
bne.un
的MSDN文档说明了几乎相同的事情:“当使用无符号整数或无序浮点值进行比较时,如果value1不等于value2,则bne.un指令将控制权转移到指定的目标指令”。我只是认为“无符号整数”位是错误的
  .method public static char  test(char x) cil managed
  {
    // Code size       11 (0xb)
    .maxstack  8
    IL_0000:  ldc.i4.s   97
    IL_0002:  ldarg.0
    IL_0003:  beq.s      IL_0008

    IL_0005:  ldc.i4.s   65
    IL_0007:  ret

    IL_0008:  ldc.i4.s   66
    IL_000a:  ret
  }
    L0000: movzx eax, dx
    L0003: cmp eax, 0x41
    L0006: jne short L000e   ; will be je for `!=`
    L0008: mov eax, 1
    L000d: ret
    L000e: xor eax, eax
    L0010: ret