gpt4 book ai didi

c# - 某些编译器发出的奇怪 IL 代码

转载 作者:太空狗 更新时间:2023-10-30 00:31:01 25 4
gpt4 key购买 nike

我一直在查看我挖出的一些旧的 (Reflector) 反编译源代码。该 DLL 最初是使用 .NET 2.0 从 Visual Basic .NET 源代码编译的——除此之外我再也没有关于编译器的信息。

在某个时候发生了一些奇怪的事情。代码中有一个分支没有被遵循,即使条件应该成立。准确地说,这是分支:

[...]
if (item.Found > 0)
{
[...]

现在,有趣的部分是如果 item.Found 为 -1,则进入了 if 语句的范围。 item.Found 的类型是 int

为了弄清楚发生了什么,我查看了 IL 代码并找到了这个:

ldloc.3 
ldfld int32 Info::Found
ldc.i4.0
cgt.un
stloc.s flag3
ldloc.s flag3
brfalse.s L_0024

显然 Reflector 在这里是错误的。正确的反编译代码应该是:

if ((uint)item.Found > (uint)0) 
{ ... }

到目前为止上下文还可以。现在回答我的问题。

首先,我无法想象有人真的在写这段代码; IMO 没有一个头脑清醒的人会以这种方式区分“-1”和“0”——这是“Found”唯一可以拥有的两个值。

所以,这让我得出结论,编译器做了一些我不理解的事情。

  • 到底为什么/在什么情况下编译器会生成这样的 IL 代码?此检查(而不是 ceqbne_un - 这是我所期望的,通常由 C# 生成)有什么好处?
  • 相关:最有可能的原始源代码是什么?

最佳答案

看起来很古怪,但这与以前版本的 Visual Basic 有关,即以 VB6 结尾的那一代。它有一个非常不同的 bool 类型表示,a VARIANT_BOOL .这仍然是 VB.NET 中的一个因素,因为它需要支持遗留代码。

True 的值表示不同,它是 -1。 False 是 0,就像在 .NET 中一样。

虽然这看起来也是一个非常古怪的选择,但任何其他语言都使用 1 来表示 True,这是有非常的充分理由的。它使逻辑运算符和数学运算符 AndOr 运算符之间的区别消失了。这很好,程序员不必学习的又一件事。从大多数 C# 程序员编写的代码类型来看,这是一个学习障碍,他们在 if() 语句中盲目地应用 &&|| 是很明显的。即使这样做不是一个好主意,由于机器代码中所需的短路分支,这些运算符的开销也很大。如果处理器的分支预测对左操作数的预测很差,那么由于流水线停顿,您很容易丢失大量 CPU 周期。

不错,但并非没有问题,AndOr 总是对左右操作数求值。而且它有触发异常的诀窍,有时你确实需要短路。 VB.NET 添加了 AndAlsoOrElse 运算符来解决这个问题。

所以 cgt.un 是有道理的,它可以处理 .NET bool 值 遗留值。它不关心 True 值是 -1 还是 1。也不关心变量或表达式实际上是 bool 值,在 VB.NET 中允许 Option Strict Off。

关于c# - 某些编译器发出的奇怪 IL 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30774480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com