Чтение онлайн

ЖАНРЫ

ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Троелсен Эндрю

Шрифт:

Формально объект, используемый для хранения набора значений, называется виртуальным стеком выполнения. Вы сможете убедиться в том, что CIL предлагает целый ряд кодов операций, которые используются для добавления значения в стек: соответствующий процесс называется загрузкой. Точно так же CIL определяет целый ряд других кодов операций, которые переносят значение с вершины стека в память (например, в локальную переменную): для обозначения этого процесса используется термин сохранение.

В CIL просто невозможно получить доступ к элементам данных непосредственно, и это касается как локально определенных переменных,

так и входных аргументов методов, а также полей данных типов. Нужно сначала явно загрузить элемент в стек, чтобы затем "вытолкнуть" его оттуда для дальнейшего использования (помните об этом, ведь именно поэтому блок программного кода CIL может казаться несколько избыточным).

Чтобы понять, как CIL использует стековую модель, рассмотрим простой C#-метод PrintMessage, который не имеет аргументов и ничего не возвращает. В рамках реализации этого метода вы просто выводите значение локальной строковой переменной в поток стандартного вывода.

public void PrintMessage {

 string myMessage = "Привет.";

 Consolе.WriteLine(myMessage);

}

Если рассмотреть результат трансляции этого метода компилятором C# в термины CIL, вы сразу заметите, что метод PrintMessage определяет ячейку хранения для локальной переменной, используя директиву.locals. Локальная строка затем загружается и сохраняется в этой локальной неременной с помощью кодов операций ldstr (загрузка строки) и stloc.0 (это можно прочитать, как "запомнить текущее значение в локальной переменной с индексом 0").

Значение (снова с индексом 0) затем загружается в память с помощью кода операции ldloc.0 ("загрузить локальный аргумент с индексом 0") для использования в вызове метода System.Console.WriteLine (указанном с помощью кода операции call). Наконец, происходит возврат из функции через код операции ret.

.method public hidebysig instance void PrintMessage cil managed {

 .maxstack 1

 // Определение локальной строковой переменной (с индексом 0).

 .locals init ([0] string myMessage)

 // Загрузка строки со значением "Привет."

 ldstr "Привет."

 // Сохранение строкового значения в стеке в локальной переменной.

 stloc.0

 // Загрузка значения с индексом 0.

 ldloc.0

 // Вызов метода с текущим значением.

 call void [mscorlib]System.Console::WriteLine(string)

 ret

}

Замечание. В программном коде CIL поддерживаются комментарии, использующие синтаксис двойной косой черты (а также синтаксис /*…*/). Как и в C#, компилятором CIL комментарии просто игнорируются.

Челночная технология разработки

Вы уже знаете, как использовать ildasm.exe для просмотра программного кода CIL, генерируемого компилятором C#. Однако вы можете не знать о том, что ildasm.exe позволяет записать CIL-код, содержащийся в загруженном компоновочном блоке, во внешний файл. Имея программный код CIL в своем распоряжении, вы можете отредактировать и с помощью ildasm.exe –

компилятора CIL – скомпилировать базовый код вновь.

Формально такой подход называется челночной технологией разработки, и эта технология может оказаться полезной в следующих случаях.

• Перед вами стоит задача изменить компоновочный блок, для которого нет исходного кода.

• Ввиду несовершенства компилятора языка .NET, сгенерировавшего неэффективный программный код CIL, вы хотите изменить этот код.

• Вы создаете компоновочные блоки, взаимодействующие в рамках COM, и вам приходится принимать во внимание то, что некоторые атрибуты IDL (Interface Definition Language – язык описания интерфейса) в процессе преобразования могут теряться (например, COM-атрибут [helpstring]).

Для примера использования челночной технологии разработки создайте новый файл (HelloProgram.cs) исходного кода C# с помощью обычного текстового редактора и определите в этом файле следующий тип класса (можете, конечно, использовать и Visual Studio 2005, но тогда не забудьте удалить файл AssemblyInfo.cs, чтобы уменьшить объем генерируемого CIL-кода).

// Простое консольное приложение на языке C#.

using System;

class Program {

 static void Main(string[] args) {

Console.WriteLine("Hello CIL code!");

Console.ReadLine;

 }

}

Сохраните этот файл в подходящем месте на своем диске и скомпилируйте его с помощью программы csc.exe.

csc HelloProgram.cs

Теперь откройте полученный файл HelloProgram.exe с помощью ildasm.exe и, используя опцию меню File->Dump, сохраните "сырой" программный код CIL в новом файле *.il (HelloProgram.il) На вашем жестком диске (значения, предлагаемые в появляющемся диалоговом окне, вполне подойдут для наших целей). Теперь вы можете рассмотреть этот файл, используя любой текстовый редактор. Вот слегка откорректированный в снабженный некоторыми комментариями результат.

// Компоновочные блоки, на которые мы ссылаемся.

.assembly extern mscorlib {

 .publickeytoken = (В7 7A 5С 56 19 34 Е0 89)

 .ver 2:0:0:0

}

// Ваш компоновочный блок.

.assembly HelloProgram {

 .hash algorithm 0х00008004

.ver 0:0:0:0

}

.module HelloProgram.exe

.imagebase 0x00400000

.file alignment 0x00000200

.stackreserve 0x00100000

.subsystem 0x0003

.corflags 0x00000001

// Определение класса Program.

.class private auto ansi beforefieldinit Program extends [mscorlib]System.Object {

 .method private hidebysig static void Main(string[] args) cil managed {

// Обозначение этого метода, как точки входа

Поделиться с друзьями: