Рабочим названием платформы .NET было |
Язык CIL: инструкции для поддержки объектной модели
Инструкции для работы с массивами
В принципе, массивы являются такими же объектами, как и экземпляры других классов. Но для более эффективной реализации и для сокращения размеров CIL-кода в наборе инструкций CLI предусмотрена специальная инструкция для работы с одномерными массивами, индексируемыми с нуля.
Создание массивов
Инструкция newarr (см. таблицу 3.30) выделяет память под одномерный массив, индексируемый с нуля. Тип элементов массива указывается через токен метаданных во встроенном операнде инструкции (в качестве типа элементов может выступать тип-значение).
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x8D | newarr | token | Создает новый массив с элементами указанного типа |
Диаграмма стека для инструкции newarr:
... , num -> ... , array
Инструкция newarr потребляет со стека вычислений размер массива (на диаграмме обозначен как num ) и оставляет объектную ссылку на созданный массив в куче.
Элементы созданного массива автоматически обнуляются.
Загрузка длины массива
Инструкция ldlen (см. таблицу 3.31) загружает размер одномерного массива на стек вычислений.
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x8E | ldlen | - | Загружает на стек длину массива |
Диаграмма стека для инструкции ldlen:
... , array -> ... , length
Инструкция потребляет со стека объектную ссылку на массив и оставляет на стеке его размер в виде числа типа native unsigned int.
Работа с элементами массивов
Инструкции ldelem (см. таблицу 3.32) предназначены для загрузки значения элемента одномерного массива на стек вычислений.
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x90 | ldelem.i1 | - | Загрузить элемент типа int8 |
0x91 | ldelem.u1 | - | Загрузить элемент типа unsigned int8 |
0x92 | ldelem.i2 | - | Загрузить элемент типа int16 |
0x93 | ldelem.u2 | - | Загрузить элемент типа unsigned int16 |
0x94 | ldelem.i4 | - | Загрузить элемент типа int32 |
0x95 | ldelem.u4 | - | Загрузить элемент типа unsigned int32 |
0x96 | ldelem.i8 (ldelem.u8) | - | Загрузить элемент типа int64 или unsigned int64 |
0x97 | ldelem.i | - | Загрузить элемент типа native int или unsigned native int |
0x98 | ldelem.r4 | - | Загрузить элемент типа float32 |
0x99 | ldelem.r8 | - | Загрузить элемент типа float64 |
0x9A | ldelem.ref | - | Загрузить элемент - объектную ссылку |
Так как в процессе JIT-компиляции не отслеживаются точные типы объектных ссылок на стеке вычислений, то JIT-компилятору требуются указания о том, элементы какого типа содержатся в массиве. Поэтому для разных типов существуют разные варианты инструкции ldelem.
Следует иметь в виду, что значения целых типов, разрядность которых меньше 32 бит, при загрузке на стек удлиняются. Значения со знаком и значения без знака удлиняются по-разному, поэтому наличие отдельных инструкций для знаковых и беззнаковых целых типов вполне объяснимы. При этом остается неясным, для чего потребовалось определять две инструкции ldelem.i4 и ldelem.u4 для 32-разрядных целых типов, потому что они, очевидно, имеют одинаковый эффект.
Диаграмма стека для инструкций ldelem выглядит следующим образом:
... , array, index -> ... , value
Инструкция потребляет со стека объектную ссылку на массив и индекс элемента (типа native int ), значение которого надо загрузить.
Инструкция ldelema (см. таблицу 3.33) загружает на стек вычислений адрес элемента одномерного массива (управляемый указатель). Тип элементов массива указывается через токен метаданных во встроенном операнде инструкции (в качестве типа элементов может выступать тип-значение). Диаграмма стека для нее выглядит следующим образом:
... , array, index -> ... , addr
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x8F | ldelema | token | Загружает адрес элемента массива с указанным индексом |
Инструкции stelem (см. таблицу 3.34) предназначены для сохранения значения со стека вычислений в элементе одномерного массива. Аналогично инструкциям ldelem, существуют различные варианты stelem для разных типов элементов массива. При этом варианты stelem для беззнаковых целых типов отсутствуют за ненадобностью.
Диаграмма стека для инструкций stelem:
... , array, index, value -> ...
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x9C | stelem.i1 | - | Сохраняет значение типа int8 в элементе массива с указанным индексом |
0x9D | stelem.i2 | - | Сохраняет значение типа int16 в элементе массива с указанным индексом |
0x9E | stelem.i4 | - | Сохраняет значение типа int32 в элементе массива с указанным индексом |
0x9F | stelem.i8 | - | Сохраняет значение типа int64 в элементе массива с указанным индексом |
0xA0 | stelem.r4 | - | Сохраняет значение типа float32 в элементе массива с указанным индексом |
0xA1 | stelem.r8 | - | Сохраняет значение типа float64 в элементе массива с указанным индексом |
0xA2 | stelem.ref | - | Сохраняет значение объектной ссылки в элементе массива с указанным индексом |
0x9B | stelem.i | - | Сохраняет значение типа native int в элементе массива с указанным индексом |