2

これが私のプログラム simpleCsharp.exe であるとします。

namespace simpleCsharp
{
    public class Program
    {       
         public static int Main(string[] args)
        {
                uint x = 0xFEFEFE;
                uint y = 0xEEEEEE;
                uint z;
                uint[] list = { 0, 1, 2, 4, 8 };
                uint[] array = { 0xA, 0xB, 0xC, 0xD };
                z = x + y + list[2] + array[1];
                z = z - (y << 1);
                return 0;           
        }
    }
}

Debug の [Disassembly] ウィンドウで単純な C# プログラムの逆アセンブリを表示すると、ネイティブ コードの出力は少なくともある程度意味のあるものになります。たとえば、最適化をオンにして、メインのデバッグの逆アセンブリを次に示します。

uint x = 0xFEFEFE;
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  sub         esp,28h 
00000006  xor         eax,eax 
00000008  mov         dword ptr [ebp-14h],eax 
0000000b  mov         dword ptr [ebp-18h],eax 
0000000e  mov         dword ptr [ebp-4],ecx 
00000011  cmp         dword ptr ds:[037D14ACh],0 
00000018  je          0000001F 
0000001a  call        763B370F 
0000001f  xor         edx,edx 
00000021  mov         dword ptr [ebp-0Ch],edx 
00000024  xor         edx,edx 
00000026  mov         dword ptr [ebp-1Ch],edx 
00000029  xor         edx,edx 
0000002b  mov         dword ptr [ebp-20h],edx 
0000002e  xor         edx,edx 
00000030  mov         dword ptr [ebp-8],edx 
00000033  xor         edx,edx 
00000035  mov         dword ptr [ebp-10h],edx 
00000038  mov         dword ptr [ebp-8],0FEFEFEh 
uint y = 0xEEEEEE;
0000003f  mov         dword ptr [ebp-0Ch],0EEEEEEh 
uint z;
uint[] list = { 0, 1, 2, 4, 8 };
00000046  mov         edx,5 
0000004b  mov         ecx,79882916h 
00000050  call        FD95FD70 
00000055  mov         dword ptr [ebp-24h],eax 
00000058  lea         ecx,[ebp-14h] 
0000005b  mov         edx,37D25E0h 
00000060  call        761A4716 
00000065  lea         eax,[ebp-14h] 
00000068  push        dword ptr [eax] 
0000006a  mov         ecx,dword ptr [ebp-24h] 
0000006d  call        761A47F3 
00000072  mov         eax,dword ptr [ebp-24h] 
00000075  mov         dword ptr [ebp-1Ch],eax 
uint[] array = { 0xA, 0xB, 0xC, 0xD };
00000078  mov         edx,4 
0000007d  mov         ecx,79882916h 
00000082  call        FD95FD70 
00000087  mov         dword ptr [ebp-28h],eax 
0000008a  lea         ecx,[ebp-18h] 
0000008d  mov         edx,37D25ECh 
00000092  call        761A4716 
00000097  lea         eax,[ebp-18h] 
0000009a  push        dword ptr [eax] 
0000009c  mov         ecx,dword ptr [ebp-28h] 
0000009f  call        761A47F3 
000000a4  mov         eax,dword ptr [ebp-28h] 
000000a7  mov         dword ptr [ebp-20h],eax 
z = x + y + list[2] + array[1];
000000aa  mov         eax,dword ptr [ebp-8] 
000000ad  add         eax,dword ptr [ebp-0Ch] 
000000b0  mov         edx,dword ptr [ebp-1Ch] 
000000b3  cmp         dword ptr [edx+4],2 
000000b7  ja          000000BE 
000000b9  call        763B6900 
000000be  add         eax,dword ptr [edx+10h] 
000000c1  mov         edx,dword ptr [ebp-20h] 
000000c4  cmp         dword ptr [edx+4],1 
000000c8  ja          000000CF 
000000ca  call        763B6900 
000000cf  add         eax,dword ptr [edx+0Ch] 
000000d2  mov         dword ptr [ebp-10h],eax 
z = z - (y << 1);
000000d5  mov         eax,dword ptr [ebp-0Ch] 
000000d8  add         eax,eax 
000000da  sub         dword ptr [ebp-10h],eax 
return 0;           
000000dd  xor         eax,eax 
000000df  mov         esp,ebp 
000000e1  pop         ebp 
000000e2  ret 

ただし、同じ C# アセンブリで DUMPBIN を実行すると (Debug Info = "None" で、バイトだけが表示されません)、つまり

dumpbin "simpleCsharp.exe" /disasm /out:"simpleCsharp_dump.txt"

生成されたファイルのネイティブ コード出力は、Debug の Disassembly で見たものとあまり似ていません。dumpbin のファイルには、デバッグの逆アセンブリからの命令や値が 1 つも表示されません。したがって、2 行のネイティブ コード (上記) はどこにも見つかりません。これは、Visual Studio (2010) から生成されたアセンブリで dumpbin を実行する場合でも、ngen.exe を使用てネイティブ イメージを生成し、ネイティブ イメージ ファイル simpleCsharp.ni.exe で dumpbin を実行する場合でも当てはまります。

デバッグでは最適化がオンになっており、ビルドはリリースに設定されています。デバッグを実行するアセンブリと ngen に与えるアセンブリの唯一の違いは、Debug Info = "None" です。

dumpbin simpleCsharp.ni.exe /disasm

以下は、ネイティブ イメージ ファイルに対して dumpbin を実行したときの simpleCsharp プログラムの逆アセンブリです。

https://docs.google.com/leaf?id=0B9u9yFU99BOcYjNmNGRmNTItZjQ0NC00YmI0LWEyZTQtNjdkNDdhYTc2MmNm&hl=ja

少なくとも FEFEFE または EEEEEE という数字が dumpbin の出力のどこかに表示されることを期待していますが、それは Debug Disassembly にも表示されます。

同じプログラムに対して、ネイティブ イメージ ファイルからの dumpbin 出力に Debug の逆アセンブリ コードが1行も表示されない理由を誰か説明してもらえますか? 最適化のためである場合は、少し詳細を教えていただけますか?

ありがとう

4

1 に答える 1

6

ジャストインタイムコンパイラのことを忘れています。アセンブリにはマシンコードが含まれていません。実行時に、アセンブリ内のILからのジッターによって生成されます。ildasm.exeやReflectorなどのツールを使用して、アセンブリ内のILを確認できます。Dumpbin.exeのサポートは不十分で、CLRヘッダーをダンプする可能性があります。

ngen-edイメージには、ジッターによって最適化されたマシンコードが含まれていることに注意してください。そのオプティマイザは、マシンコードを大幅に変更します。デバッガーでは、最適化はデフォルトでオフになっています。これを確認するには、リリースビルドをデバッグし、デバッガオプションを変更する必要があります。[ツール]+[オプション]、[デバッグ]、[一般]で、[モジュールの読み込み時にJIT最適化を抑制する]オプションのチェックを外します。また、生成されたコードは、jittedではなくプリコンパイルされているため、場所によってはまったく異なる可能性があることに注意してください。ジッタは、事前に利用できない知識を持っているため、より良い仕事をすることができます。

于 2011-04-04T13:37:12.497 に答える