Рейтинговые книги
Читем онлайн ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 132 133 134 135 136 137 138 139 140 ... 259

.method public hidebysig static void CountToTen() cil managed {

 .maxstack 2

 .locals init ([0] int32 i) // Инициализация локальной целой 'i'.

 IL_0000: ldc.i4.0 // Загрузка этого значения в стек.

 IL_0001: stloc.0 // Сохранение значения под индексом '0'.

 IL_0002: br.s IL_0008 // Переход к IL_0008.

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

 IL_0005: ldc.i4.1 // Загрузка значения '1' в стек.

 IL_0006: add // Добавление в стек под индексом 0.

 IL_0007: stloc.0

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

 IL_0009: ldc.i4.s 10 // Загрузка значения '10' в стек.

 IL_000b: blt.s IL_0004 // Меньше? Если да, то к 1L_0004.

 IL_000d: ret

}

В сущности, этот программный код CIL начинается с определения локальной переменной int32 и загрузки ее в стек. Затем осуществляются переходы между командами с метками IL_0008 и IL_0004, причем каждый раз значение i увеличивается на 1 и проверяется, осталось ли это значение меньше 10. Если нет, то происходит выход из метода.

Создание компоновочного блока .NET в CIL

Теперь, освоив синтаксис и семантику CIL, вы можете закрепить свои знания на практике, построив приложение .NET с использованием только CIL и текстового редактора. Ваше приложение будет состоять из приватного одномодульного *.dll, содержащего два определения типов класса, и консольного *.exe, взаимодействующего с этими типами.

Создание CILCars.dll

Первым делом следует построить файл *.dll для использования клиентом. Откройте любой текстовый редактор и создайте новый файл *.il с именем CILCars.il. Этот одномодульный компоновочный блок будет использовать два внешних двоичных файла .NET, поэтому вы можете начать свой файл программного кода CIL так.

// Ссылка на mscorlib.dll и

// System.Windows.Forms.dll

.assemblу extern mscorlib {

 .publickeytoken = (B7 7A 5С 56 19 34 E0 89)

 .ver 2:0:0:0

}

.assembly extern System.Windows.Forms {

 .publickeytoken = (B7 7A 5C 56 19 34 E0 89)

 .ver 2:0:0:0

}

// Определение одномодульного компоновочного блока.

.assembly CILCars {

 .hash algorithm 0х00008004

 .ver 1:0:0:0

}

.modulе СILCars.dll

Как уже было сказано, этот компоновочный блок будет содержать два типа класса. Первый тип, CILCar, определяет два поля данных и пользовательский конструктор. Второй тип, CarInfoHelper, определяет единственный статический метод с именем DisplayCarInfо(), который использует CILCar в качестве параметра и возвращает void. Оба типа находятся в пространстве имен CILCars. В терминах CIL класс CILCar можно реализовать так.

// Реализация типа CILCars.CILCar.

.namespace CILCars {

 .class public auto ansi beforefieldinit CILCar extends [mscorlib]System.Object {

  // Поле данных CILCar.

.field public string petName

  .field public int32 currSpeed

  // Пользовательский конструктор, который дает пользователю

  // возможность присвоить полю данные.

  .method public hidebysig specialname rtspecialname instance void .ctor(int32 c, string p) cil managed {

   .maxstack 8

   // Загрузка первого аргумента в стек и вызов

   // конструктора базового класса.

   ldarg.0 // объект 'this', а не int32!

   call instance void [mscorlib]System.Object::.ctor()

   // Теперь загрузка первого и второго аргументов в стек.

   ldarg.0 // объект 'this'

   ldarg.1 // аргумент int32

   // Сохранение элемента вершины стека (int 32) в поле currSpeed.

   stfld int32 CILCars.CILCar::currSpeed

   // Загрузка строкового аргумента и сохранение в поле petName.

   ldarg.0 // объект 'this'

   ldarg.2 // аргумент string

   stfld string CILCars.CILCar::petName

   ret

  }

 }

}

Имея в виду, что настоящим первым аргументом любого нестатического члена является объектная ссылка this, в первом блоке CIL-кода мы просто загружаем эту объектную ссылку и вызываем конструктор базового класса. Затем поступающие аргументы конструктора помещаются в стек и запоминаются в полях данных типа с помощью кода операции stfld (сохранение в поле).

Далее, вы должны реализовать второй тип в данном пространстве имен, а именно тип CILCarInfo. Суть типа находится в статическом методе Display(). Основной задачей этого метода является получение поступающего параметра CILCar, извлечение значения поля данных и вывод его в окне сообщения Windows Forms. Вот полная реализация CILCarInfo, а далее следует ее анализ.

.class public auto ansi beforefieldinit CILCarInfo extends [mscorlib]System.Object {

 .method public hidebysig static void Display(class CILCars.CILCar c) cil managed {

  .maxstасk 8

  // Нам нужна локальная строковая переменная.

  .locals init ([0] string caption)

  // Загрузка строки и входного CILCar в стек.

  ldstr "Скорость [0]: "

  ldarg.0

  // Помещение значения petName класса CILCar в стек и

  // вызов статического метода String.Format().

  ldfld string CILCars.CILCar::petName

  call string [mscorlib]System.String::Format(string, object)

  stloc.0

  // Загрузка значения поля currSpeed и получение его строкового // представления (обратите внимание на вызов ToString()).

  ldarg.0

  ldflda int32 CILCars.CILCar::currSpeed

  call instance string [mscorlib]System.Int32::ToString()

  ldloc.0

  // Вызов метода MessageBox.Show() с загруженными значениями.

  call valuetype [System.Windows.Forms] System.Windows.Forms.DialogResult [Sуstem.Windоws.Forms] System.Windows.Forms.MessageBox::Show(string, string)

  pop

  ret

 }

}

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

Метод начинается с загрузки строки ("Скорость {0}: ") в стек за которой следует аргумент CILCar. Когда эти два значения оказываются в нужном месте, загружается значение поля petName и вызывается статический метод System.String. Format(), чтобы вместо замещающих фигурных скобок получить имя CILCar.

Та же общая процедура выполняется и при обработке поля currSpeed, но следует отметить, что здесь используется код. операции ldarga, которая загружает адрес аргумента в стек. Затем вызывается System.Int32.ToString(), чтобы преобразовать значение, размещенное по указанному адресу, в строковый тип. Наконец, когда обе строки отформатированы так, как требуется, вызывается метод MessageBox.Show().

Теперь вы можете скомпилировать свой новый файл *.dll с помощью ilasm.exe, используя команду

ilasm /dll CILCars.il

а затем проверить полученный CIL-код с помощью peverifу.exe.

peverify CILCars.dll

Создание CILCarClient.exe

Теперь нам нужно построить простой компоновочный блок *.exe, который должен выполнить следующее.

• Создать тип CILCar.

• Передать этот тип статическому методу CILCarInfo.Display(),

Создайте новый файл *.il и определите внешние ссылки на mscorlib.dll и CILCars.dll (не забудьте поместить копию этого компоновочного блока .NET в каталог приложения клиента!). Затем определите единственный тип (Program), который использует компоновочный блок CILCars.dll. Вот соответствующий программный код, приведенный полностью.

// Ссылки на внешние компоновочные блоки.

.assembly extern mscorlib {

 .publickeytoken = (B7 7A 5C 56 19 34 E0 89)

 .ver 2:0:0:0

}

.assembly extern CILCars {

 .ver 1:0:0:0

}

// Наш выполняемый компоновочный блок.

.assembly CILCarClient {

 .hash algorithm 0x00008004

 .ver 0:0:0:0

}

.module CILCarClient.exe

// Реализация типа Program.

.namespace CILCarClient {

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

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

   // Обозначает точку входа *.exe.

   .entrypoint

   .maxstack 8

   // Объявление локального типа CILCar и добавление в стек

   // значений для вызова конструктора.

   .locals init ([0] class [CILCars]CILCars.CILCar myCilCar)

   ldc.i4 55

   ldstr "Junior"

   // Создание нового CILCar: сохранение и загрузка ссылки.

   newobj: instance void [CILCars] CILCars.CILCar::.сtor(int32, string)

   stloc.0

   ldloc.0

   // Вызов Display() и передача верхнего значения из стека.

1 ... 132 133 134 135 136 137 138 139 140 ... 259
На этой странице вы можете бесплатно читать книгу ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен бесплатно.
Похожие на ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен книги

Оставить комментарий