Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 351 352 353 354 355 356 357 358 359 ... 642

}

Первым шагом при размещении локальных переменных с помощью CIL является применение директивы .locals в паре с атрибутом init. Каждая переменная идентифицируется своим типом данных и необязательным именем. После определения локальных переменных значения загружаются в стек (с использованием различных кодов операций загрузки) и сохраняются в этих локальных переменных (с помощью кодов операций сохранения).

Отображение параметров на локальные переменные в CIL

Вы уже видели, каким образом объявляются локальные переменные в CIL с применением директивы .locals init; однако осталось еще взглянуть на то, как входные параметры отображаются на локальные переменные. Рассмотрим показанный ниже статический метод С#:

public static int Add(int a, int b)

{

  return a + b;

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

}

Такой с виду невинный метод требует немалого объема кодирования на языке CIL. Во-первых, входные аргументы (а и b) должны быть помещены в виртуальный стек выполнения с использованием кода операции ldarg (load argument — загрузить аргумент). Во-вторых, с помощью кода операции add из стека будут извлечены следующие два значения и просуммированы с сохранением результата обратно в стек. В-третьих, сумма будет извлечена из стека и возвращена вызывающему коду посредством кода операции ret. Дизассемблировав этот метод C# с применением ildasm.exe, вы обнаружите множество дополнительных лексем, которые были внедрены в процессе компиляции, но основная часть кода CIL довольно проста:

.method public hidebysig static int32 Add(int32 a,

  int32 b) cil managed

{

  .maxstack 2

  ldarg.0 // Загрузить а в стек.

  ldarg.1 // Загрузить b в стек.

  add     // Сложить оба значения.

  ret

}

Скрытая ссылка this

Обратите внимание, что ссылка на два входных аргумента (а и b) в коде CIL производится с использованием их индексных позиций (0 и 1), т.к. индексация в виртуальном стеке выполнения начинается с нуля.

Во время исследования или написания кода CIL нужно помнить о том, что каждый нестатический метод, принимающий входные аргументы, автоматически получает неявный дополнительный параметр, который представляет собой ссылку на текущий объект (подобно ключевому слову this в С#). Скажем, если бы метод Add() был определен как нестатический:

<b>// Больше не является статическим!</b>

public int Add(int a, int b)

{

  return a + b;

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

}

то входные аргументы а и b загружались бы с применением кодов операций ldarg.1 и ldarg.2 (а не ожидаемых ldarg.0 и ldarg.1). Причина в том, что ячейка 0 содержит неявную ссылку this. Взгляните на следующий псевдокод:

<b>// Это ТОЛЬКО псевдокод!</b>

.method public hidebysig static int32 AddTwoIntParams(

  MyClass_HiddenThisPointer this, int32 a, int32 b) cil managed

{

  ldarg.0 // Load MyClass_HiddenThisPointer onto the stack.

  ldarg.1 // Load &quot;a&quot; onto the stack.

  ldarg.2 // Load &quot;b&quot; onto the stack.

...

}

Представление итерационных конструкций в CIL

Итерационные конструкции в языке программирования C# реализуются посредством ключевых слов for, foreach, while и do, каждое из которых имеет специальное представление в CIL. В качестве примера рассмотрим следующий классический цикл

for:

public static void CountToTen()

{

  for(int i = 0; i &lt; 10; i++)

  {

  }

}

Вспомните, что для управления прекращением потока выполнения, когда удовлетворено некоторое условие, используются коды операций br (br, bltn т.д.). В приведенном примере указано условие, согласно которому выполнение цикла for должно прекращаться, когда значение локальной переменной i становится больше или равно 10. С каждым проходом к значению i добавляется 1, после чего проверяемое условие оценивается заново.

Также вспомните, что в случае применения любого кода операции CIL, предназначенного для ветвления, должна быть определена специфичная метка кода (или две), обозначающая место, куда будет произведен переход при истинном результате оценки условия. С учетом всего сказанного рассмотрим показанный ниже (отредактированный) код CIL, который сгенерирован утилитой ildasm.exe (вместе с автоматически созданными метками):

.method public hidebysig static void CountToTen() cil managed

{

  .maxstack 2

  .locals init (int32 V_0, bool V_1)

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

1 ... 351 352 353 354 355 356 357 358 359 ... 642
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю бесплатно.
Похожие на Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю книги

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