дизассемблирование C#: почему машинный код DUMPBIN так отличается от дизассемблирования Debug?
Предположим, что это моя программа 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;
}
}
}
Если я просматриваю дизассемблирование простой программы на C# в окне дизассемблирования Debug, то вывод собственного кода, по крайней мере, имеет некоторый смысл. Например, вот отладочная разборка Main, с оптимизацией по:
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
Однако, если я запускаю DUMPBIN на той же сборке C# (с Debug Info = "None", поэтому он не просто показывает байты), т. е.
dumpbin "simpleCsharp.exe" /disasm /out:"simpleCsharp_dump.txt"
Нативный код, выводимый в сгенерированном файле, даже не очень похоже на то, что я видел в Debug's Disassembly. Я не вижу ни одной инструкции или значения из разборки отладки в файле из dumpbin. Таким образом, 2 строки машинного кода (выше) нигде не найдены. Это происходит независимо от того, запускаю ли я dumpbin на сборке, созданной из Visual Studio (2010), или использую нген.exe чтобы создать собственный образ и запустить dumpbin в файле собственного образа simpleCsharp.ni.exe.
Оптимизация-это на в Debug, и сборка настроена на выпуск, единственное различие между сборкой, на которой я запускаю отладку, и сборкой, которую я даю ngen, - это Debug Info = "None".
dumpbin simpleCsharp.ni.exe /disasm
Вот дизассемблирование программы simpleCsharp при запуске dumpbin в файле native image:
Https://docs.google.com/leaf?id=0B9u9yFU99BOcYjNmNGRmNTItZjQ0NC00YmI0LWEyZTQtNjdkNDdhYTc2MmNm&hl=en
Я бы, по крайней мере, ожидал увидеть число FEFEFE или EEEEEE, отображаемое в выводе dumpbin где-то, и это действительно появляется в отладочной разборке.
Не мог бы кто-нибудь объяснить, почему я не вижу одну строку кода дизассемблирования Debug в выводе dumpbin из файла native image для той же программы? Если это из-за оптимизации, не могли бы вы рассказать немного подробнее?
Спасибо
1 ответ:
Вы забываете о компиляторе just-in-time. Сборка не содержит машинного кода, она генерируется во время выполнения дрожанием от IL в сборке. Вы можете посмотреть на IL в сборке с помощью таких инструментов, как ildasm.ехе или рефлектор. Программа dumpbin.exe имеет плохую поддержку, он может сбросить заголовок CLR, вот и все.
Обратите внимание, что изображение ngen-ed содержит машинный код, оптимизированный дрожанием. Этот оптимизатор очень сильно изменяет машинный код. Оптимизация-это выключено по умолчанию в отладчике. Чтобы увидеть его, необходимо отладить сборку выпуска и изменить параметр отладчика. Tools + Options, Debugging, General, снимите флажок "подавлять оптимизацию JIT при загрузке модуля". Также имейте в виду, что сгенерированный код может просто отличаться местами, потому что он был предварительно скомпилирован вместо jitted. Дрожание может сделать лучшую работу, потому что у него есть знания, которые не доступны заранее.