如果声明工作不正确 - 反汇编对我没有任何解释

时间:2012-01-13 00:48:37

标签: c# disassembly

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

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

在我现在的代码中:

Int32 errorCode32 = errorCode;
Int32 errorTimeout = 300;

if (errorCode32.Equals(errorTimeout) == false)
{
    System.Console.Out.WriteLine("aaa");
    return;
}

其中errorCode等于300.所以乍一看它是可见的,如果不应该执行errorCode == 300而不是if语句中的代码,因为它被定义为仅当errorCode不等于300时执行

直到现在一切都很清楚,但现在整个乐趣开始了。

应用程序正在运行,并执行带有上述代码段的方法。 errorCode等于300,预期的结果是应用程序不会在if语句中执行任何代码,因为整个语句是false。但实际上应用程序进入“if”并立即跳转到“return”语句。 System.Console.Out ...永远不会执行。如果我用“throw new SomeException()”

替换干净的“return”语句
Int32 errorCode32 = errorCode;
Int32 errorTimeout = 300;

if (errorCode32.Equals(errorTimeout) == false)
{
    System.Console.Out.WriteLine("aaa");
    throw new SomeException();
}

我会得到相同的结果。应用程序进入if语句(注意:[errorCode32.Equals(errorTimeout)== false]在我的情况下为false),不执行Console.Out ...但抛出SomeException。

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

我很困惑,我甚至反汇编代码,看看会发生什么(即使我不是汇编程序的专家)。但结果对我来说很奇怪。

反汇编代码如下:

    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行时,应用程序立即跳转到行

00000134  mov         eax,dword ptr ds:[0302CE34h]

我无法理解这里发生了什么。我试图通过互联网搜索,但我找不到任何有用的东西。有没有人有什么建议可能是问题的原因或解决方法?


修改

我忘记了使用Visual Studio 2008并编译成.NET 3.5的信息。 已安装所有更新。


修改

C#中的整个方法

        private void nativeDocumentServiceWrapper_PostInvokeEvents(object sender, WebServiceInvokeEventArgs e)
        {
            Exception exception = e.Exception;
            if (exception == null)
            {
                _invokeRetries = 0;
                return;
            }

            string errorCodeString = ErrorHandler.GetErrorCodeString(exception);
            int errorCode;
            if (int.TryParse(errorCodeString, out errorCode))
            {
                e.Exception = new VaultException(errorCode, exception);
            }

            Int32 errorCode32 = errorCode;
            Int32 errorTimeout = 300;

            if (errorCode32.Equals(errorTimeout) == false)
            {
                System.Console.Out.WriteLine("aaa");
                return;
            }

            Trace.TraceWarning("Invoke failed (count: {4}) {0}.{1} #{2} error '{3}'", _moduleName, e.MethodName, _id, errorCodeString, _invokeRetries + 1);

            if (_invokeRetries > 0)
            {
                //int errorCode;
                if (int.TryParse(errorCodeString, out errorCode))
                {
                    //throw new VaultException(errorCode, exception);
                    e.Exception = new VaultException(errorCode, exception);
                }
                return;
            }

            e.Exception = null;

            // we ran into error 300 or 319
            // the solution is to log in again and re-run the command

            tryReloginAndInvokeVaultMethodAgain(e);
        }

并反汇编:

    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:             }

2 个答案:

答案 0 :(得分:2)

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

没有任何错误。但是,如果您希望逐步调试调试器以正常工作,则必须禁用优化。

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

答案 1 :(得分:0)

我花了更多的时间来调查这个问题,我有一些我想分享的结论,即使这意味着我必须承认我做了几个错误的假设而且我无法全面了解整个行为

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

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

1    if (someVariable)
2    {
3        someCode();
4        someOtherCode();
5        throw someExceptionPassedFromTheThirdPartyLibrary;
6    }
7    somethingElse();

调试器在第1行停止,someVariable为false,跳过,调试器在第5行等待。在这里我做了第一个错误的假设 - 就是我的异常从这里抛出。

第三:我开始尝试了。 “someVariable”总是假的,但有时调试器从第1行跳到第7行,有时从1跳到5.我决定使用反汇编程序。

第四:我无法理解反汇编代码的行为,它使我的思想固定在想法上,即if语句行为不正确。另外我发现文章“http://stackoverflow.com/questions/6054987/if-statement-appears-to-be-evaluating-even-when-condition-evaluates-to-false”[已确认的JIT bug]这次帮助了我。

好的我认为在经过一些额外的背景后,现在是时候解释我的代码中发生了什么。

一般情况下,在我的情况下,“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.此时我无法理解这里实际发生了什么,所以我假设它只是执行“返回”指令。事实很简单 - “if from 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”指令内部执行,但不执行该指令。这是一个错误 - 但不是“if”处理,只在VS调试器中。此外,该错误并不重要,因为它实际上只是表示,并且对调试的代码没有任何影响。