Язык программирования C#9 и платформа .NET5
IL_0011: ret} // end of method '<Program>$'::'<Main>$'Роль меток в коде CIL
Вы определенно заметили, что каждая строка в коде реализации предваряется лексемой в форме
XX: (например,IL_X,IL_0000:и т.д.). Такие лексемы называются метками кода и могут именоваться в любой выбранной вами манере (при условии, что они не дублируются внутри области действия члена). При сбросе содержимого сборки в файл утилитаIL_0001:автоматически генерирует метки кода, которые следуют соглашению об именовании видаildasm.exe. Однако их можно заменить более описательными маркерами, например:IL_XXXX:.method private hidebysig static void Main(string[] args) cil managed{.entrypoint.maxstack 8Nothing_1: nopLoad_String: ldstr "Hello CIL code!"PrintToConsole: call void [System.Console]System.Console::WriteLine(string)Nothing_2: nopWaitFor_KeyPress: call string [System.Console]System.Console::ReadLine()RemoveValueFromStack: popLeave_Function: ret}В сущности, большая часть меток кода совершенно не обязательна. Единственный случай, когда метки кода по-настоящему необходимы, связан с написанием кода CIL, в котором используются разнообразные конструкции ветвления или организации циклов, т.к. с помощью меток можно указывать, куда должен быть направлен поток логики. В текущем примере все автоматически сгенерированные метки кода можно удалить безо всяких последствий:
.method private hidebysig static void Main(string[] args) cil managed{.entrypoint.maxstack 8nopldstr "Hello CIL code!"call void [System.Console]System.Console::WriteLine(string)nopcall string [System.Console]System.Console::ReadLine()popret}Взаимодействие c CIL: модификация файла *.il
Теперь, когда вы имеете представление о том, из чего состоит базовый файл CIL, давайте завершим эксперимент с возвратным проектированием. Цель здесь довольно проста: изменить сообщение, которое выводится в окно консоли. Вы можете делать что-то большее, скажем, добавлять ссылки на сборки или создавать новые классы и методы, но мы ограничимся простым примером.
Чтобы внести изменение, вам понадобится модифицировать текущую реализацию операторов верхнего уровня, созданную в виде метода
. Отыщите этот метод в файле<Main>$()и измените сообщение на*.il."Hello from altered CIL code!"Фактически код CIL был модифицирован для соответствия следующему определению на языке С#:
static void Main(string[] args){Console.WriteLine("Hello from altered CIL code!");Console.ReadLine();}Компиляция кода CIL
Предшествующие версии .NET позволяли компилировать файлы
с применением утилиты ilasm.exe. В .NET Core положение дел изменилось. Для компиляции файлов*.ilвы должны использовать тип проекта*.il. На момент написания главы он все еще не был частью стандартного комплекта SDK.Microsoft.NET.Sdk.ILНачните с создания нового каталога на своей машине. Создайте в этом каталоге файл
, который применяется к текущему каталогу и всем его подкаталогам. Он используется для определения версии комплекта SDK, которая будет задействована при запуске команд .NET Core CLI. Модифицируйте содержимое файла, как показано ниже:global.json{"msbuild-sdks": {"Microsoft.NET.Sdk.IL": "5.0.0-preview.1.20120.5"}}На следующем шаге создается файл проекта. Создайте файл по имени
и приведите его содержимое к следующему виду:RoundTrip.ilproj<Project Sdk="Microsoft.NET.Sdk.IL"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net5.0</TargetFramework><MicrosoftNetCoreIlasmPackageVersion>5.0.0-preview.1.20120.5</MicrosoftNetCoreIlasmPackageVersion><ProduceReferenceAssembly>false</ProduceReferenceAssembly></PropertyGroup></Project>Наконец, скопируйте созданный файл
в каталог проекта. Скомпилируйте сборку с применением .NET Core CLI:RoundTrip.ildotnet buildРезультирующие файлы будут находиться, как обычно, в подкаталоге
. На этом этапе новое приложение можно запустить. Разумеется, в окне консоли отобразится обновленное сообщение. Хотя приведенный простой пример не является особенно впечатляющим, он иллюстрирует один из сценариев применения возвратного проектирования на CIL.bin\debug\net5.0Директивы и атрибуты CIL
Теперь, когда вы знаете, как преобразовывать сборки .NET Core в файлы
и компилировать файлы*.ilв сборки, можете переходить к более детальному исследованию синтаксиса и семантики языка CIL. В последующих разделах будет поэтапно рассматриваться процесс создания специального пространства имен, содержащего набор типов. Тем не менее, для простоты типы пока не будут иметь логики реализации своих членов. Разобравшись с созданием простых типов, можете переключить внимание на процесс определения "реальных" членов с использованием кодов операций CIL.*.il