C# 如果语句工作不正确-反汇编对我来说没有任何解释

C# 如果语句工作不正确-反汇编对我来说没有任何解释,c#,disassembly,C#,Disassembly,我遇到了一个非常奇怪的问题 我正在开发一些连接到Web服务的类库。该库由桌面应用程序使用 在我现在的代码中: Int32 errorCode32 = errorCode; Int32 errorTimeout = 300; if (errorCode32.Equals(errorTimeout) == false) { System.Console.Out.WriteLine("aaa"); return; } 其中errorCode等于300。因此,乍一看,if error

我遇到了一个非常奇怪的问题

我正在开发一些连接到Web服务的类库。该库由桌面应用程序使用

在我现在的代码中:

Int32 errorCode32 = errorCode;
Int32 errorTimeout = 300;

if (errorCode32.Equals(errorTimeout) == false)
{
    System.Console.Out.WriteLine("aaa");
    return;
}
其中errorCode等于300。因此,乍一看,if errorCode==300时,if语句中的代码不应执行,因为它被定义为仅在errorCode不等于300时执行

直到现在一切都很清楚,但现在一切都开始了

应用程序正在运行,并执行带有上述代码段的方法。errorCode等于300,这是预期的结果,即应用程序不会执行if语句中的任何代码,因为整个语句为false。但实际上,应用程序进入“if”内部并立即跳转到“return”语句。系统控制台输出。。。永远不会被执行。如果我将干净的“return”语句替换为“thrownewsomeexception()”

我会得到同样的结果。应用程序进入if语句(注意:[errorCode32.Equals(errorTimeout)==false]在我的例子中为false],不执行Console.Out。。。但也有例外

我多次重建了所有内容,删除了所有二进制文件,甚至从磁盘上删除了整个项目,并再次从存储库中检索到“清理”文件夹

我非常困惑,甚至将代码反汇编以查看发生了什么(即使我不是汇编专家)。但结果对我来说很奇怪

反汇编代码如下:

    50:                 Int32 errorCode32 = errorCode;
000000e5  mov         eax,dword ptr [ebp-50h] 
000000e8  mov         dword ptr [ebp-54h],eax 
    51:                 Int32 errorTimeout = 300;
000000eb  mov         dword ptr [ebp-58h],12Ch 
    52: 
    53:                 if (errorCode32.Equals(errorTimeout) == false)
000000f2  lea         ecx,[ebp-54h] 
000000f5  mov         edx,dword ptr [ebp-58h] 
000000f8  call        699EB198 
000000fd  mov         dword ptr [ebp-68h],eax 
00000100  movzx       eax,byte ptr [ebp-68h] 
00000104  mov         dword ptr [ebp-48h],eax 
00000107  cmp         dword ptr [ebp-48h],0 
0000010b  jne         00000134 
    54:                 {
0000010d  nop              
    55:                     System.Console.Out.WriteLine("aaa");
0000010e  call        69538768 
00000113  mov         dword ptr [ebp+FFFFFF7Ch],eax 
00000119  mov         edx,dword ptr ds:[0302CE30h] 
0000011f  mov         ecx,dword ptr [ebp+FFFFFF7Ch] 
00000125  mov         eax,dword ptr [ecx] 
00000127  call        dword ptr [eax+000000D8h] 
0000012d  nop              
    56:                     return;
0000012e  nop              
0000012f  jmp         00000287 
00000134  mov         eax,dword ptr ds:[0302CE34h] 
0000013a  mov         dword ptr [ebp-6Ch],eax 
0000013d  mov         edx,5 
00000142  mov         ecx,6EDE3FBEh 
00000147  call        FA68D488 
0000014c  mov         dword ptr [ebp-70h],eax 
    57:                 }
当我调试指令时,我可以理解发生了什么,直到行:

00000104  mov         dword ptr [ebp-48h],eax
我预计eax中存储的值将被复制到位置“dword ptr[ebp-48h]”,应用程序将转到下一行(00000107)。但这并没有发生。当我试图跳过第00000104行时,应用程序立即跳到第00000104行

00000134  mov         eax,dword ptr ds:[0302CE34h]
我不明白这里发生了什么。我试图在网上搜索,但找不到任何有用的东西。有没有人对问题的原因或解决方法有什么建议


编辑

我忘了把我正在使用VisualStudio2008并编译到.NET3.5中的信息放进去。 所有更新都已安装


编辑

C语言中的整型方法#

拆卸和拆卸:

    34:             private void nativeDocumentServiceWrapper_PostInvokeEvents(object sender, WebServiceInvokeEventArgs e)
    35:             {
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  sub         esp,84h 
0000000c  mov         esi,ecx 
0000000e  lea         edi,[ebp-54h] 
00000011  mov         ecx,12h 
00000016  xor         eax,eax 
00000018  rep stos    dword ptr es:[edi] 
0000001a  mov         ecx,esi 
0000001c  xor         eax,eax 
0000001e  mov         dword ptr [ebp-1Ch],eax 
00000021  mov         dword ptr [ebp-3Ch],ecx 
00000024  mov         dword ptr [ebp-40h],edx 
00000027  cmp         dword ptr ds:[01AD2DD8h],0 
0000002e  je          00000035 
00000030  call        6AB8A719 
00000035  mov         dword ptr [ebp-48h],0 
0000003c  xor         edx,edx 
0000003e  mov         dword ptr [ebp-5Ch],edx 
00000041  xor         edx,edx 
00000043  mov         dword ptr [ebp-44h],edx 
00000046  xor         edx,edx 
00000048  mov         dword ptr [ebp-4Ch],edx 
0000004b  xor         edx,edx 
0000004d  mov         dword ptr [ebp-58h],edx 
00000050  nop              
    36:                 Exception exception = e.Exception;
00000051  mov         eax,dword ptr [ebp+8] 
00000054  mov         eax,dword ptr [eax+4] 
00000057  mov         dword ptr [ebp-44h],eax 
    37:                 if (exception == null)
0000005a  cmp         dword ptr [ebp-44h],0 
0000005e  setne       al   
00000061  movzx       eax,al 
00000064  mov         dword ptr [ebp-48h],eax 
00000067  cmp         dword ptr [ebp-48h],0 
0000006b  jne         0000007F 
    38:                 {
0000006d  nop              
    39:                     _invokeRetries = 0;
0000006e  mov         eax,dword ptr [ebp-3Ch] 
00000071  xor         edx,edx 
00000073  mov         dword ptr [eax+00000088h],edx 
    40:                     return;
00000079  nop              
0000007a  jmp         00000287 
    41:                 }
    42: 
    43:                 string errorCodeString = ErrorHandler.GetErrorCodeString(exception);
0000007f  mov         ecx,dword ptr [ebp-44h] 
00000082  call        FF0827F0 
00000087  mov         dword ptr [ebp-60h],eax 
0000008a  mov         eax,dword ptr [ebp-60h] 
0000008d  mov         dword ptr [ebp-4Ch],eax 
    44:                 int errorCode;
    45:                 if (int.TryParse(errorCodeString, out errorCode))
00000090  lea         edx,[ebp-50h] 
00000093  mov         ecx,dword ptr [ebp-4Ch] 
00000096  call        694B44A8 
0000009b  mov         dword ptr [ebp-64h],eax 
0000009e  cmp         dword ptr [ebp-64h],0 
000000a2  sete        al   
000000a5  movzx       eax,al 
000000a8  mov         dword ptr [ebp-48h],eax 
000000ab  cmp         dword ptr [ebp-48h],0 
000000af  jne         000000E5 
    46:                 {
000000b1  nop              
    47:                     e.Exception = new VaultException(errorCode, exception);
000000b2  mov         ecx,5482E0Ch 
000000b7  call        FA68D364 
000000bc  mov         dword ptr [ebp+FFFFFF78h],eax 
000000c2  push        dword ptr [ebp-44h] 
000000c5  mov         edx,dword ptr [ebp-50h] 
000000c8  mov         ecx,dword ptr [ebp+FFFFFF78h] 
000000ce  call        FF07FCB0 
000000d3  mov         edx,dword ptr [ebp+8] 
000000d6  mov         eax,dword ptr [ebp+FFFFFF78h] 
000000dc  lea         edx,[edx+4] 
000000df  call        6A90E288 
    48:                 }
000000e4  nop              
    49: 
    50:                 Int32 errorCode32 = errorCode;
000000e5  mov         eax,dword ptr [ebp-50h] 
000000e8  mov         dword ptr [ebp-54h],eax 
    51:                 Int32 errorTimeout = 300;
000000eb  mov         dword ptr [ebp-58h],12Ch 
    52: 
    53:                 if (errorCode32.Equals(errorTimeout) == false)
000000f2  lea         ecx,[ebp-54h] 
000000f5  mov         edx,dword ptr [ebp-58h] 
000000f8  call        699EB198 
000000fd  mov         dword ptr [ebp-68h],eax 
00000100  movzx       eax,byte ptr [ebp-68h] 
00000104  mov         dword ptr [ebp-48h],eax 
00000107  cmp         dword ptr [ebp-48h],0 
0000010b  jne         00000134 
    54:                 {
0000010d  nop              
    55:                     System.Console.Out.WriteLine("aaa");
0000010e  call        69538768 
00000113  mov         dword ptr [ebp+FFFFFF7Ch],eax 
00000119  mov         edx,dword ptr ds:[0302CE30h] 
0000011f  mov         ecx,dword ptr [ebp+FFFFFF7Ch] 
00000125  mov         eax,dword ptr [ecx] 
00000127  call        dword ptr [eax+000000D8h] 
0000012d  nop              
    56:                     return;
0000012e  nop              
0000012f  jmp         00000287 
00000134  mov         eax,dword ptr ds:[0302CE34h] 
0000013a  mov         dword ptr [ebp-6Ch],eax 
0000013d  mov         edx,5 
00000142  mov         ecx,6EDE3FBEh 
00000147  call        FA68D488 
0000014c  mov         dword ptr [ebp-70h],eax 
    57:                 }
    58: 
    59:                 Trace.TraceWarning("Invoke failed (count: {4}) {0}.{1} #{2} error '{3}'", _moduleName, e.MethodName, _id, errorCodeString, _invokeRetries + 1);
0000014f  mov         eax,dword ptr [ebp-70h] 
00000152  mov         dword ptr [ebp-5Ch],eax 
00000155  mov         eax,dword ptr [ebp-3Ch] 
00000158  push        dword ptr [eax+00000080h] 
0000015e  mov         ecx,dword ptr [ebp-5Ch] 
00000161  xor         edx,edx 
00000163  call        6A914654 
00000168  mov         eax,dword ptr [ebp+8] 
0000016b  push        dword ptr [eax+8] 
0000016e  mov         ecx,dword ptr [ebp-5Ch] 
00000171  mov         edx,1 
00000176  call        6A914654 
0000017b  mov         ecx,6F052DA0h 
00000180  call        FA68D364 
00000185  mov         dword ptr [ebp-74h],eax 
00000188  mov         eax,dword ptr [ebp-5Ch] 
0000018b  mov         dword ptr [ebp+FFFFFF74h],eax 
00000191  mov         eax,dword ptr [ebp-3Ch] 
00000194  mov         eax,dword ptr [eax+00000084h] 
0000019a  mov         edx,dword ptr [ebp-74h] 
0000019d  mov         dword ptr [edx+4],eax 
000001a0  mov         eax,dword ptr [ebp-74h] 
000001a3  push        eax  
000001a4  mov         ecx,dword ptr [ebp+FFFFFF74h] 
000001aa  mov         edx,2 
000001af  call        6A914654 
000001b4  push        dword ptr [ebp-4Ch] 
000001b7  mov         ecx,dword ptr [ebp-5Ch] 
000001ba  mov         edx,3 
000001bf  call        6A914654 
000001c4  mov         ecx,6F052DA0h 
000001c9  call        FA68D364 
000001ce  mov         dword ptr [ebp-78h],eax 
000001d1  mov         eax,dword ptr [ebp-5Ch] 
000001d4  mov         dword ptr [ebp+FFFFFF70h],eax 
000001da  mov         eax,dword ptr [ebp-3Ch] 
000001dd  mov         eax,dword ptr [eax+00000088h] 
000001e3  inc         eax  
000001e4  mov         edx,dword ptr [ebp-78h] 
000001e7  mov         dword ptr [edx+4],eax 
000001ea  mov         eax,dword ptr [ebp-78h] 
000001ed  push        eax  
000001ee  mov         ecx,dword ptr [ebp+FFFFFF70h] 
000001f4  mov         edx,4 
000001f9  call        6A914654 
000001fe  mov         edx,dword ptr [ebp-5Ch] 
00000201  mov         ecx,dword ptr [ebp-6Ch] 
00000204  call        69039D88 
00000209  nop              
    60: 
    61:                 if (_invokeRetries > 0)
0000020a  mov         eax,dword ptr [ebp-3Ch] 
0000020d  cmp         dword ptr [eax+00000088h],0 
00000214  setle       al   
00000217  movzx       eax,al 
0000021a  mov         dword ptr [ebp-48h],eax 
0000021d  cmp         dword ptr [ebp-48h],0 
00000221  jne         00000273 
    62:                 {
00000223  nop              
    63:                     //int errorCode;
    64:                     if (int.TryParse(errorCodeString, out errorCode))
00000224  lea         edx,[ebp-50h] 
00000227  mov         ecx,dword ptr [ebp-4Ch] 
0000022a  call        694B44A8 
0000022f  mov         dword ptr [ebp-7Ch],eax 
00000232  cmp         dword ptr [ebp-7Ch],0 
00000236  sete        al   
00000239  movzx       eax,al 
0000023c  mov         dword ptr [ebp-48h],eax 
0000023f  cmp         dword ptr [ebp-48h],0 
00000243  jne         00000270 
    65:                     {
00000245  nop              
    66:                         //throw new VaultException(errorCode, exception);
    67:                         e.Exception = new VaultException(errorCode, exception);
00000246  mov         ecx,5482E0Ch 
0000024b  call        FA68D364 
00000250  mov         dword ptr [ebp-80h],eax 
00000253  push        dword ptr [ebp-44h] 
00000256  mov         edx,dword ptr [ebp-50h] 
00000259  mov         ecx,dword ptr [ebp-80h] 
0000025c  call        FF07FCB0 
00000261  mov         edx,dword ptr [ebp+8] 
00000264  mov         eax,dword ptr [ebp-80h] 
00000267  lea         edx,[edx+4] 
0000026a  call        6A90E288 
    68:                     }
0000026f  nop              
    69:                     return;
00000270  nop              
00000271  jmp         00000287 
    70:                 }
    71: 
    72:                 e.Exception = null;
00000273  mov         eax,dword ptr [ebp+8] 
00000276  xor         edx,edx 
00000278  mov         dword ptr [eax+4],edx 
    73: 
    74:                 // we ran into error 300 or 319
    75:                 // the solution is to log in again and re-run the command
    76: 
    77:                 tryReloginAndInvokeVaultMethodAgain(e);
0000027b  mov         edx,dword ptr [ebp+8] 
0000027e  mov         ecx,dword ptr [ebp-3Ch] 
00000281  call        FF0876C0 
00000286  nop              
    78:             }

您启用了优化,编译器将
if
语句中的return语句与函数末尾的语句组合在一起。这两行代码的地址相同,调试器无法判断要突出显示哪一行源代码,因为两者都匹配

没什么不对的。但是,如果您希望单步执行调试器以正常工作,则必须禁用优化


这只是优化器可以用来混淆调试器的几件事情之一。其他的可能性是对没有数据依赖关系的语句进行重新排序(以优化管道),甚至将语句拆分并在语句之间放置另一个语句。

我花了更多的时间研究这个问题,我有一些结论想与大家分享,即使这意味着我必须承认,我做出了一些错误的假设,我无法从整体上了解整个行为

第一:我介绍的代码旨在处理使用第三方库时的一些特定问题。这些库的未记录行为是,在某些情况下,它在某些条件下抛出异常。最初的问题来自这样一个事实,即即使我们“处理”了错误情况,库也抛出了异常

第二:调试时发现如下情况:

1    if (someVariable)
2    {
3        someCode();
4        someOtherCode();
5        throw someExceptionPassedFromTheThirdPartyLibrary;
6    }
7    somethingElse();
调试器在第1行停止,someVariable为false,跳过,调试器正在第5行等待。这里我做了第一个错误的假设,就是我的异常是从这里抛出的

第三:我开始做实验。“someVariable”始终为false,但有时调试器从第1行跳到第7行,有时从第1行跳到第5行。我决定使用反汇编程序

第四:我无法理解反汇编代码的行为,它使我的想法根深蒂固,即if语句的行为不正确。此外,我还发现了一篇文章“http://stackoverflow.com/questions/6054987/if-statement-appears-to-be-evaluating-even-when-condition-evaluates-to-false“[确认JIT错误]这一次对我没有帮助

好的,我认为在一些额外的背景知识之后,是时候解释一下我的代码中到底发生了什么

一般来说,在我的情况下,“if”语句的行为是正确的。当我学到更多关于汇编程序和现代处理器体系结构的知识时,我明白了这一点

    53:                 if (errorCode32.Equals(errorTimeout) == false)
000000f2  lea         ecx,[ebp-54h] 
000000f5  mov         edx,dword ptr [ebp-58h] 
000000f8  call        699EB198 
000000fd  mov         dword ptr [ebp-68h],eax 
00000100  movzx       eax,byte ptr [ebp-68h] 
00000104  mov         dword ptr [ebp-48h],eax 
00000107  cmp         dword ptr [ebp-48h],0 
0000010b  jne         00000134 
    54:                 {
0000010d  nop              
    55:                     System.Console.Out.WriteLine("aaa");
0000010e  call        69538768 
00000113  mov         dword ptr [ebp+FFFFFF7Ch],eax 
00000119  mov         edx,dword ptr ds:[0302CE30h] 
0000011f  mov         ecx,dword ptr [ebp+FFFFFF7Ch] 
00000125  mov         eax,dword ptr [ecx] 
00000127  call        dword ptr [eax+000000D8h] 
0000012d  nop              
    56:                     return;
0000012e  nop              
0000012f  jmp         00000287 
00000134  mov         eax,dword ptr ds:[0302CE34h] 
0000013a  mov         dword ptr [ebp-6Ch],eax 
0000013d  mov         edx,5 
00000142  mov         ecx,6EDE3FBEh 
00000147  call        FA68D488 
0000014c  mov         dword ptr [ebp-70h],eax 
    57:                 }
偏移量00000104-0000010b处指令的执行由处理器体系结构优化(可能发生跳转预测,或其他一些核心处理器优化)。所以,处理器不调用三条指令,而是一步完成所有操作。因为00000107中应该比较的值不相等,所以处理器跳到00000134。在这一点上,我无法理解这里到底发生了什么,所以我假设它只是执行“return”指令。事实很简单——“从if返回”指令并不像我想象的那样位于00000134,但指令更大——位于0000012f,这只是简单的无条件跳转

当我理解这一点时,我知道这段代码的行为是正确的。所以我又搬到了C#,我发现了一些让我感到羞愧的事情。因为当我再次调试代码时,我发现它的行为是这样的:

1    if (someVariable)
2    {
3        someCode();
4        someOtherCode();
5        throw someExceptionPassedFromTheThirdPartyLibrary;
6    }
7    somethingElse();
断点位于1,F10 当前线路指示器位于5,按F10 当前线路指示器位于7,按F10。。。等等


所以我知道调试器会在最后一条“if”指令中执行,但不会执行。这是一个bug,但不是在“if”处理中,而是仅在VS调试器中。此外,这个bug并不重要,因为它实际上只是一个演示,对调试的代码没有任何影响。

Adam-这是我首先检查的。Pl
    53:                 if (errorCode32.Equals(errorTimeout) == false)
000000f2  lea         ecx,[ebp-54h] 
000000f5  mov         edx,dword ptr [ebp-58h] 
000000f8  call        699EB198 
000000fd  mov         dword ptr [ebp-68h],eax 
00000100  movzx       eax,byte ptr [ebp-68h] 
00000104  mov         dword ptr [ebp-48h],eax 
00000107  cmp         dword ptr [ebp-48h],0 
0000010b  jne         00000134 
    54:                 {
0000010d  nop              
    55:                     System.Console.Out.WriteLine("aaa");
0000010e  call        69538768 
00000113  mov         dword ptr [ebp+FFFFFF7Ch],eax 
00000119  mov         edx,dword ptr ds:[0302CE30h] 
0000011f  mov         ecx,dword ptr [ebp+FFFFFF7Ch] 
00000125  mov         eax,dword ptr [ecx] 
00000127  call        dword ptr [eax+000000D8h] 
0000012d  nop              
    56:                     return;
0000012e  nop              
0000012f  jmp         00000287 
00000134  mov         eax,dword ptr ds:[0302CE34h] 
0000013a  mov         dword ptr [ebp-6Ch],eax 
0000013d  mov         edx,5 
00000142  mov         ecx,6EDE3FBEh 
00000147  call        FA68D488 
0000014c  mov         dword ptr [ebp-70h],eax 
    57:                 }
1    if (someVariable)
2    {
3        someCode();
4        someOtherCode();
5        throw someExceptionPassedFromTheThirdPartyLibrary;
6    }
7    somethingElse();