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