您在.NET 4 x86抖动中发现了代码生成错误。这是非常不寻常的,只有在代码未优化时它才会失败。机器代码如下:
State a = s[0, 0];
013F04A9 push 0 ; index 2 = 0
013F04AB mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04AE xor edx,edx ; index 1 = 0
013F04B0 call 013F0058 ; eax = s[0, 0]
013F04B5 mov dword ptr [ebp-4Ch],eax ; $temp1 = eax
013F04B8 movsx eax,byte ptr [ebp-4Ch] ; convert sbyte to int
013F04BC mov dword ptr [ebp-44h],eax ; a = s[0, 0]
Console.WriteLine(a == s[0, 0]); // False
013F04BF mov eax,dword ptr [ebp-44h] ; a
013F04C2 mov dword ptr [ebp-50h],eax ; $temp2 = a
013F04C5 push 0 ; index 2 = 0
013F04C7 mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04CA xor edx,edx ; index 1 = 0
013F04CC call 013F0058 ; eax = s[0, 0]
013F04D1 mov dword ptr [ebp-54h],eax ; $temp3 = eax
; <=== Bug here!
013F04D4 mov eax,dword ptr [ebp-50h] ; a == s[0, 0]
013F04D7 cmp eax,dword ptr [ebp-54h]
013F04DA sete cl
013F04DD movzx ecx,cl
013F04E0 call 731C28F4
带有很多临时性和代码重复的令人毛骨悚然的事情,这对于未优化的代码是正常的。值得注意的是013F04B8处的指令,即发生了从sbyte到32位整数的必要转换。数组getter辅助函数返回0x0000000FF,等于State.BUG,在比较该值之前需要将其转换为-1(0xFFFFFFFF)。MOVSX指令是符号扩展指令。
013F04CC再次发生相同的情况,但是这次没有 MOVSX指令进行相同的转换。那就是芯片掉落的地方,CMP指令将0xFFFFFFFF与0x000000FF进行比较,这是错误的。因此,这是一个遗漏错误,代码生成器无法再次发出MOVSX来执行相同的字节数到int的转换。
此错误特别不寻常的是,当启用优化器时,此错误可以正常运行,现在知道在两种情况下都使用MOVSX。
长时间未发现此错误的可能原因是使用sbyte作为枚举的基本类型。很少做。使用多维数组也是有帮助的,这种组合是致命的。
否则,我会说一个非常严重的错误。很难猜到它有多广泛,我只测试了4.6.1 x86抖动。x64和3.5 x86抖动会生成完全不同的代码,并避免出现此错误。继续进行的临时解决方法是删除sbyte作为枚举基类型,并将其作为默认值int,因此不需要符号扩展。
您可以在connect.microsoft.com上提交该错误,链接到该Q + A应该足以告诉他们他们需要知道的一切。如果您不想花时间,请告诉我,我会解决。