ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Во-первых, обратите внимание на то, что файл *.il начинается с объявления всех внешних компоновочных блоков, на которые ссылается данный компоновочный блок. Здесь вы видите только одну директиву .assembly extern для одного обязательно присутствующего mscorlib.dll. Если бы ваша библиотека классов использовала типы из других внешних компоновочных блоков, вы бы обнаружили дополнительные директивы .assembly extern.
Далее следует формальное определение вашего компоновочного блока HelloProgram.exe, для которого указана версия 0.0.0.0, назначаемая по умолчанию (если вы не укажете иное значение с помощью атрибута [AssemblyVersion]). После этого приводятся другие описания компоновочного блока, для которых используются другие директивы CIL (такие, как .module, .imagebase и т.д.).
После указания ссылок на внешние компоновочные блоки и определения текущего компоновочного блока идет определение типа Program. Обратите внимание на то, что директива.class имеет несколько атрибутов (многие из которых необязательны), – например, атрибут extends, задающий базовый класс типа.
Большой кусок программного кода CIL соответствует конструктору класса, заданному по умолчанию, и методу Main. Оба они определены (в частности) с помощью директивы .method. После определения этих членов с помощью подходящих директив и атрибутов они реализуются с помощью различных кодов операций.
Важно понять, что в CIL при взаимодействии с типами .NET (например, с System.Console) всегда необходимо использовать абсолютные имена типов. Более того, к абсолютному имени типа всегда должен добавляться (в квадратных скобках) префикс с понятным именем компоновочного блока, определяющего этот тип. Взгляните на CIL-реализацию Main.
Реализация конструктора, заданного по умолчанию, в терминах программного кода CIL включает еще одну относящуюся к загрузке инструкцию (ldarg.0). В данном случае значение загружается в стек не как пользовательская переменная, указанная нами, а как текущая объектная ссылка (подробности этого процесса будут описаны позже). Также обратите внимание на то, что конструктор, заданный по умолчанию, явно вызывает конструктор базового класса.
Роль меток в программном коде CIL
Вы. конечно, заметили, что в каждой строке программного кода реализации содержится префикс в форме лексемы IL_XXX: (например, IL_0000: IL_0001: и т.д.). Эти лексемы называются метками кода, и они могут иметь любой вид, какой вы только пожелаете (лишь бы они не дублировались в пределах одного и того же контекста). При записи содержимого компоновочного блока в файл с помощью ildasm.exe автоматически генерируются метки кода, имеющие вид IL_XXX:. Но вы можете изменить их с тем, чтобы они стали более информативными.
Суть в том, что большинство меток кода совсем необязательно. Единственным случаем, когда метки кода оказываются по-настоящему полезными (и обязательными), является случай, когда в программном коде CIL используются ветвления или циклические конструкции. Например, в нашем случае вы можете исключить метки вообще.
Взаимодействие с CIL: модификация файла *.il
Теперь, когда вы понимаете, как компонуется базовый файл CIL, давайте завершим наш эксперимент с челночной технологией разработки программ. С помощью изменения CIL-кода в файле *.il мы должны выполнить следующее.
• Добавить ссылку на компоновочный блок System.Windows.Forms.dll.
• Загрузить локальную строку в Main.
• Вызвать метод System.Windows.Forms.MessageBox.Show, используя локальную строковую переменную в качестве его аргумента.
Первым шагом является добавление новой директивы.assembly (с атрибутом extern), которая укажет, что используется System.Windows.Forms.dll. Для этого просто добавьте в файл *.il следующую программную логику после ссылки на внешний компоновочный блок mscorlib.