Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 49 стр.

UptoLike

Особого внимания заслуживает встроенный операнд для инструкции
switch. Эта инструкция осуществляет множественный условный переход в
зависимости от некоторого целого значения, которое берется из стека вы-
числений. Ее встроенный операнд представляет собой массив адресов пе-
реходов. Он кодируется следующим образом: сначала идет 32-разрядное
целое число без знака, обозначающее количество адресов переходов (раз-
мер массива), затем следуют сами адреса. При этом каждый адрес кодиру-
ется в виде 32-разрядного целого числа со знаком.
Рассмотрим примеры кодирования инструкций CIL:
1. Инструкция ldarg.0 загружает на стек вычислений значение
первого аргумента метода. Она является сокращенной версией
инструкции ldarg, не содержит встроенных операндов и имеет
код 0x02:
/* 02 */ ldarg.0
2. Инструкция arglist загружает на стек вычислений специаль-
ный описатель массива переменных параметров метода. Она
не содержит встроенных операндов и имеет двухбайтовый код
0xFE 0x00:
/* FE 00 */ arglist
3. Инструкция ldc.i4.s 16 загружает на стек вычислений целочис-
ленную константу 16. Она является сокращенной версией инст-
рукции ldc.i4, имеет код 0x1F и содержит встроенный операнд
типа int8:
/* 1F | 10 */ ldc.i4.s 16
4. Инструкция ldc.r4 1.0 загружает на стек вычисления число 1.0
(константу с плавающей запятой). Она имеет код 0x22 и содер-
жит встроенный операнд типа float32:
/* 22 | 0000803F */ ldc.r4 1.0
5. Инструкция isinst System.String служит для динамической
проверки типа объекта на стеке вычислений. Она имеет код 0x75
и содержит встроенный операнд типа token, в котором хранится
токен метаданных, указывающий на тип:
/* 75 | (02)00000F */ isinst System.String
В скобки помещен первый байт токена метаданных, обозначаю-
щий номер таблицы метаданных. Обратите внимание, что зна-
чение токена метаданных для типа System.String в различных
сборках может отличаться.
6. Инструкция call System.String::Compare вызывает метод. Ее
встроенный операнд содержит токен метаданных, указываю-
щий на описание вызываемого метода:
/* 28 | (06)0000CD */ call System.String::Compare
Common Intermediate Language
85
вильных» последовательностей байт. То есть даже если поток инструкций
CIL содержит «мертвые» участки, которые никогда не получат управле-
ние, эти участки должны представлять собой правильную последователь-
ность инструкций CIL.
Разные инструкции CIL кодируются последовательностями байт различ-
ной длины. Размер каждой инструкции, а также порядок и смысл составляю-
щих ее байт определяется описанием инструкции, которое можно найти в [3].
3.1.1.1. Формат инструкции
Последовательность байт, кодирующая инструкцию CIL, начинается
с кода инструкции. Часто используемые инструкции имеют однобайтовые
коды. Инструкции, которые используются реже, имеют двухбайтовые ко-
ды (при этом первый байт всегда равен 0xFE).
В разделе, посвященном виртуальной системе выполнения VES, гово-
рилось о том, что операнды инструкций CIL размещаются на стеке вычисле-
ний. Тем не менее, многие инструкции имеют дополнительные встроенные
операнды (inline operands), которые находятся прямо в потоке инструкций.
Например, инструкция ldloc, загружающая на стек вычислений значение
локальной переменной, имеет встроенный операнд, задающий номер пере-
менной. А инструкция call, вызывающая метод, имеет встроенный операнд,
задающий токен метаданных, по которому можно найти описание вызывае-
мого метода. Встроенные операнды размещаются в потоке инструкций сра-
зу после кода инструкции. В таблице 3.1 перечислены все варианты встроен-
ных операндов. Для кодирования встроенных операндов, занимающих более
одного байта и не являющихся токенами метаданных, используется порядок
байт, при котором младший байт идет первым («little-endian»).
Таблица 3.1. Варианты встроенных операндов инструкций CIL
84
CIL и системное программирование в Microsoft .NET
Операнд Размер в байтах Описание
none 0 У некоторых инструкций встроенные
операнды отсутствуют
int8 1 Знаковое 8-битовое целое число
int32 4 Знаковое 32-битовое целое число
int64 8 Знаковое 64-битовое целое число
unsigned int8 1 Беззнаковое 8-битовое целое число
unsigned int16 2 Беззнаковое 16-битовое целое число
float32 4 32-битовое число с плавающей запятой
float64 8 64-битовое число с плавающей запятой
token 4 Токен метаданных
switch переменный Массив адресов переходов для инструк-
ции switch
84                          CIL и системное программирование в Microsoft .NET   Common Intermediate Language                                          85


вильных» последовательностей байт. То есть даже если поток инструкций                Особого внимания заслуживает встроенный операнд для инструкции
CIL содержит «мертвые» участки, которые никогда не получат управле-             switch. Эта инструкция осуществляет множественный условный переход в
ние, эти участки должны представлять собой правильную последователь-            зависимости от некоторого целого значения, которое берется из стека вы-
ность инструкций CIL.                                                           числений. Ее встроенный операнд представляет собой массив адресов пе-
     Разные инструкции CIL кодируются последовательностями байт различ-         реходов. Он кодируется следующим образом: сначала идет 32-разрядное
ной длины. Размер каждой инструкции, а также порядок и смысл составляю-         целое число без знака, обозначающее количество адресов переходов (раз-
щих ее байт определяется описанием инструкции, которое можно найти в [3].       мер массива), затем следуют сами адреса. При этом каждый адрес кодиру-
                                                                                ется в виде 32-разрядного целого числа со знаком.
3.1.1.1. Формат инструкции                                                           Рассмотрим примеры кодирования инструкций CIL:
     Последовательность байт, кодирующая инструкцию CIL, начинается                     1. Инструкция ldarg.0 загружает на стек вычислений значение
с кода инструкции. Часто используемые инструкции имеют однобайтовые                        первого аргумента метода. Она является сокращенной версией
коды. Инструкции, которые используются реже, имеют двухбайтовые ко-                        инструкции ldarg, не содержит встроенных операндов и имеет
ды (при этом первый байт всегда равен 0xFE).                                               код 0x02:
     В разделе, посвященном виртуальной системе выполнения VES, гово-                      /* 02 */ ldarg.0
рилось о том, что операнды инструкций CIL размещаются на стеке вычисле-                 2. Инструкция arglist загружает на стек вычислений специаль-
ний. Тем не менее, многие инструкции имеют дополнительные встроенные                       ный описатель массива переменных параметров метода. Она
операнды (inline operands), которые находятся прямо в потоке инструкций.                   не содержит встроенных операндов и имеет двухбайтовый код
Например, инструкция ldloc, загружающая на стек вычислений значение                        0xFE 0x00:
локальной переменной, имеет встроенный операнд, задающий номер пере-                       /* FE 00 */ arglist
менной. А инструкция call, вызывающая метод, имеет встроенный операнд,                  3. Инструкция ldc.i4.s 16 загружает на стек вычислений целочис-
задающий токен метаданных, по которому можно найти описание вызывае-                       ленную константу 16. Она является сокращенной версией инст-
мого метода. Встроенные операнды размещаются в потоке инструкций сра-                      рукции ldc.i4, имеет код 0x1F и содержит встроенный операнд
зу после кода инструкции. В таблице 3.1 перечислены все варианты встроен-                  типа int8:
ных операндов. Для кодирования встроенных операндов, занимающих более                      /* 1F | 10 */ ldc.i4.s 16
одного байта и не являющихся токенами метаданных, используется порядок                  4. Инструкция ldc.r4 1.0 загружает на стек вычисления число 1.0
байт, при котором младший байт идет первым («little-endian»).                              (константу с плавающей запятой). Она имеет код 0x22 и содер-
                                                                                           жит встроенный операнд типа float32:
     Таблица 3.1. Варианты встроенных операндов инструкций CIL                             /* 22 | 0000803F */ ldc.r4 1.0
                                                                                        5. Инструкция isinst System.String служит для динамической
Операнд        Размер в байтах Описание
                                                                                           проверки типа объекта на стеке вычислений. Она имеет код 0x75
none           0               У некоторых инструкций встроенные
                                                                                           и содержит встроенный операнд типа token, в котором хранится
                               операнды отсутствуют                                        токен метаданных, указывающий на тип:
int8           1               Знаковое 8-битовое целое число                              /* 75 | (02)00000F */ isinst System.String
int32          4               Знаковое 32-битовое целое число                             В скобки помещен первый байт токена метаданных, обозначаю-
int64          8               Знаковое 64-битовое целое число                             щий номер таблицы метаданных. Обратите внимание, что зна-
unsigned int8 1                Беззнаковое 8-битовое целое число                           чение токена метаданных для типа System.String в различных
unsigned int16 2               Беззнаковое 16-битовое целое число                          сборках может отличаться.
float32        4               32-битовое число с плавающей запятой                     6. Инструкция call System.String::Compare вызывает метод. Ее
float64        8               64-битовое число с плавающей запятой                        встроенный операнд содержит токен метаданных, указываю-
token          4               Токен метаданных                                            щий на описание вызываемого метода:
switch         переменный      Массив адресов переходов для инструк-                       /* 28 | (06)0000CD */ call System.String::Compare
                               ции switch