Формат байт-кода Dalvik

Общий дизайн

  • Модель машины и соглашения о вызовах предназначены для приблизительной имитации обычных реальных архитектур и соглашений о вызовах в стиле C:
    • Машина основана на регистрах, и размер кадров фиксируется при создании. Каждый кадр состоит из определенного количества регистров (указанных методом), а также любых дополнительных данных, необходимых для выполнения метода, таких как (но не ограничиваясь этим) программный счетчик и ссылка на файл .dex , содержащий метод. .
    • При использовании для битовых значений (таких как целые числа и числа с плавающей запятой) регистры считаются 32-битными. Соседние пары регистров используются для 64-битных значений. Для пар регистров не требуется выравнивания.
    • При использовании для ссылок на объекты регистры считаются достаточно широкими, чтобы хранить ровно одну такую ​​ссылку.
    • С точки зрения побитового представления (Object) null == (int) 0 .
    • N аргументов метода помещаются в последние N регистров кадра вызова метода по порядку. Широкие аргументы занимают два регистра. Методам экземпляра передается ссылка this в качестве первого аргумента.
  • Единицей хранения в потоке команд является 16-битная беззнаковая величина. Некоторые биты в некоторых инструкциях игнорируются/должны быть равны нулю.
  • Инструкции не ограничиваются необоснованно конкретным типом. Например, инструкции, которые перемещают значения 32-битных регистров без интерпретации, не должны указывать, перемещают ли они целые числа или числа с плавающей запятой.
  • Существуют отдельно перечисляемые и индексированные пулы констант для ссылок на строки, типы, поля и методы.
  • Побитовые литеральные данные представляются в потоке команд в строке.
  • Поскольку на практике методу редко требуется более 16 регистров, а потребность в более чем восьми регистрах довольно распространена , многие инструкции ограничиваются обращением только к первым 16 регистрам. Когда это разумно возможно, инструкции допускают обращение к первым 256 регистрам. Кроме того, у некоторых инструкций есть варианты, которые допускают гораздо большее количество регистров, включая пару инструкций универсального move , которые могут обращаться к регистрам в диапазоне v0v65535 . В случаях, когда вариант инструкции недоступен для обращения к желаемому регистру, ожидается, что содержимое регистра будет перемещено из исходного регистра в нижний регистр (перед операцией) и/или перемещено из нижнего регистра результата в старший. зарегистрироваться (после операции).
  • Существует несколько «псевдоинструкций», которые используются для хранения полезных данных переменной длины, на которые ссылаются обычные инструкции (например, fill-array-data ). Такие инструкции никогда не должны встречаться в ходе нормального выполнения. Кроме того, инструкции должны располагаться по четным смещениям байт-кода (то есть выровнены по 4 байтам). Чтобы удовлетворить этому требованию, инструменты генерации dex должны выдавать дополнительную инструкцию nop в качестве разделителя, если в противном случае такая инструкция была бы невыровнена. Наконец, хотя это и не обязательно, ожидается, что большинство инструментов предпочтут выдавать эти инструкции в конце методов, поскольку в противном случае, вероятно, потребуются дополнительные инструкции для ветвления вокруг них.
  • При установке в работающую систему некоторые инструкции могут быть изменены, меняя их формат в целях оптимизации статического связывания во время установки. Это сделано для того, чтобы обеспечить более быстрое выполнение, как только связь станет известна. Предлагаемые варианты см. в соответствующем документе по форматам инструкций . Слово «предлагается» используется намеренно; их реализация не является обязательной.
  • Человеческий синтаксис и мнемоника:
    • Порядок аргументов по принципу «назначение-затем-источник».
    • Некоторые коды операций имеют суффикс имени, устраняющий неоднозначность, указывающий тип(ы), с которыми они работают:
      • 32-битные коды операций общего типа не помечены.
      • 64-битные коды операций общего типа имеют суффикс -wide .
      • К кодам операций, зависящим от типа, добавляется их тип (или простое сокращение), один из: -boolean -byte -char -short -int -long -float -double -object -string -class -void .
    • Некоторые коды операций имеют суффикс, устраняющий неоднозначность, чтобы различать в остальном идентичные операции, которые имеют разные схемы команд или параметры. Эти суффиксы отделяются от основных имен косой чертой (" / ") и в основном существуют вообще для того, чтобы в коде, генерирующем и интерпретирующем исполняемые файлы, было взаимно-однозначное сопоставление со статическими константами (то есть для уменьшения двусмысленности). для человека).
    • В приведенных здесь описаниях ширина значения (указывающая, например, диапазон константы или количество адресованных регистров) подчеркивается использованием символа на четыре бита ширины.
    • Например, в инструкции " move-wide/from16 vAA, vBBBB ":
      • « move » — это базовый код операции, указывающий на базовую операцию (перемещение значения регистра).
      • « wide » — это суффикс имени, указывающий, что он работает с широкими (64-битными) данными.
      • « from16 » — это суффикс кода операции, указывающий вариант, который имеет 16-битную ссылку на регистр в качестве источника.
      • « vAA » — это регистр назначения (предполагаемый операцией; опять же, правило состоит в том, что аргументы назначения всегда идут первыми), который должен находиться в диапазоне v0v255 .
      • « vBBBB » — это исходный регистр, который должен находиться в диапазоне v0v65535 .
  • Дополнительную информацию о различных форматах инструкций (перечисленных в разделе «Операции и формат»), а также подробности о синтаксисе кода операции см. в документе «Форматы инструкций».
  • Дополнительную информацию о том, как байт-код вписывается в общую картину, см. в документе о формате файла .dex .

Сводка набора байт-кодов

Операция и формат Мнемоника/Синтаксис Аргументы Описание
00 10x нет Циклы отходов.

Примечание. Псевдоинструкции, несущие данные, помечаются этим кодом операции, и в этом случае старший байт блока кода операции указывает характер данных. См. «Формат packed-switch-payload », «Формат sparse-switch-payload » и «Формат fill-array-data-payload » ниже.

01 12x переместить vA, vB A: регистр назначения (4 бита)
B: исходный регистр (4 бита)
Переместить содержимое одного необъектного регистра в другой.
02 22x ход/из16 vAA, vBBBB A: регистр назначения (8 бит)
B: исходный регистр (16 бит)
Переместить содержимое одного необъектного регистра в другой.
03 32x ход/16 вАААА, вББББ A: регистр назначения (16 бит)
B: исходный регистр (16 бит)
Переместить содержимое одного необъектного регистра в другой.
04 12x широкий ход vA, vB A: пара регистров назначения (4 бита)
B: пара регистров источника (4 бита)
Переместите содержимое одной пары регистров в другую.

Примечание. Разрешено переходить от v N к v N-1 или v N+1 , поэтому реализации должны обеспечить чтение обеих половин пары регистров до того, как что-либо будет записано.

05 22x широкий ход/от 16 vAA, vBBBB A: пара регистров назначения (8 бит)
B: пара регистров источника (16 бит)
Переместите содержимое одной пары регистров в другую.

Примечание. Рекомендации по реализации такие же, как и для move-wide выше.

06 32x в ширину/16 vAAAA, vBBBB A: пара регистров назначения (16 бит)
B: пара регистров источника (16 бит)
Переместите содержимое одной пары регистров в другую.

Примечание. Рекомендации по реализации такие же, как и для move-wide выше.

07 12x перемещение объекта vA, vB A: регистр назначения (4 бита)
B: исходный регистр (4 бита)
Переместить содержимое одного регистра-носителя объекта в другой.
08 22x перемещение объекта/из 16 vAA, vBBBB A: регистр назначения (8 бит)
B: исходный регистр (16 бит)
Переместить содержимое одного регистра-носителя объекта в другой.
09 32x переместить объект/16 vAAAA, vBBBB A: регистр назначения (16 бит)
B: исходный регистр (16 бит)
Переместить содержимое одного регистра-носителя объекта в другой.
0а 11x результат перемещения vAA A: регистр назначения (8 бит) Переместите результат из одного слова, не являющийся объектом, самого последнего invoke- kind в указанный регистр. Это должно быть сделано как инструкция сразу после invoke- kind , результат которого (одно слово, не объект) не должен игнорироваться; где-либо еще недействительно.
0б 11х vAA для всего результата перемещения A: пара регистров назначения (8 бит) Переместите результат двойного слова самого последнего invoke- kind в указанную пару регистров. Это должно быть сделано как инструкция сразу после invoke- kind результат которого (двойное слово) не должен игнорироваться; где-либо еще недействительно.
0с 11х перемещение объекта-результата vAA A: регистр назначения (8 бит) Переместите результат объекта самого последнего invoke- kind в указанный регистр. Это должно быть сделано как инструкция сразу после invoke- kind или filled-new-array , результат (объекта) которого не следует игнорировать; где-либо еще недействительно.
0д 11х перемещение-исключение vAA A: регистр назначения (8 бит) Сохраните только что пойманное исключение в указанный регистр. Это должна быть первая инструкция любого обработчика исключений, перехваченное исключение которого не должно игнорироваться, и эта инструкция должна когда-либо встречаться только как первая инструкция обработчика исключений; где-либо еще недействительно.
0е 10х возврат недействителен Возврат из метода void .
0ф 11х вернуть ваа A: регистр возвращаемого значения (8 бит) Возврат из метода возврата значения одинарной ширины (32 бита), не являющегося объектом.
10 11x возвратный vAA A: пара регистров возвращаемого значения (8 бит) Возврат из метода возврата значения двойной ширины (64 бита).
11 11x возвращаемый объект vAA A: регистр возвращаемого значения (8 бит) Возврат из метода, возвращающего объект.
12 11н констант/4 ВА, #+B A: регистр назначения (4 бита)
B: целое число со знаком (4 бита)
Переместите заданное буквальное значение (с расширением знака до 32 бит) в указанный регистр.
13 21с константа/16 вАА, #+BBBB A: регистр назначения (8 бит)
B: целое число со знаком (16 бит)
Переместите заданное буквальное значение (с расширением знака до 32 бит) в указанный регистр.
14 31и const vAA, #+BBBBBBBB A: регистр назначения (8 бит)
B: произвольная 32-битная константа
Переместите данное литеральное значение в указанный регистр.
15 21ч. const/high16 vAA, #+BBBB0000 A: регистр назначения (8 бит)
B: целое число со знаком (16 бит)
Переместите заданное буквальное значение (расширенное вправо-ноль до 32 бит) в указанный регистр.
16 21с const-wide/16 vAA, #+BBBB A: регистр назначения (8 бит)
B: целое число со знаком (16 бит)
Переместите заданное буквальное значение (расширенное до 64 бит) в указанную пару регистров.
17 31и const-wide/32 vAA, #+BBBBBBBB A: регистр назначения (8 бит)
B: целое число со знаком (32 бита)
Переместите заданное буквальное значение (расширенное до 64 бит) в указанную пару регистров.
18 51л константное vAA, #+BBBBBBBBBBBBBBBB A: регистр назначения (8 бит)
B: произвольная константа двойной ширины (64 бита).
Переместите заданное буквальное значение в указанную пару регистров.
19 21ч. const-wide/high16 vAA, #+BBBB000000000000 A: регистр назначения (8 бит)
B: целое число со знаком (16 бит)
Переместите заданное буквальное значение (расширенное вправо-ноль до 64 бит) в указанную пару регистров.
1а 21в константная строка vAA, строка@BBBB A: регистр назначения (8 бит)
B: строковый индекс
Переместить ссылку на строку, указанную данным индексом, в указанный регистр.
1б 31в const-string/jumbo vAA, string@BBBBBBBB A: регистр назначения (8 бит)
B: строковый индекс
Переместить ссылку на строку, указанную данным индексом, в указанный регистр.
1с 21с vAA константного класса, тип@BBBB A: регистр назначения (8 бит)
B: индекс типа
Переместите ссылку на класс, указанный данным индексом, в указанный регистр. В случае, если указанный тип является примитивным, будет сохранена ссылка на вырожденный класс примитивного типа.
1д 11х монитор-введите vAA A: регистр ссылки (8 бит). Приобретите монитор для указанного объекта.
1e 11x монитор-выход vAA A: регистр ссылки (8 бит). Отпустите монитор для указанного объекта.

Примечание: Если эта инструкция должна выдать исключение, она должна сделать это так, как будто компьютер уже прошел эту инструкцию. Может быть полезно думать об этом как о том, что инструкция успешно выполняется (в некотором смысле), а исключение генерируется после инструкции, но до того, как следующая инструкция получит шанс выполниться. Это определение позволяет методу использовать блок сбора всех данных очистки монитора (например, finally ) в качестве очистки монитора для самого этого блока, как способ обработки произвольных исключений, которые могут быть выброшены из-за исторической реализации Thread.stop() . Thread.stop() , сохраняя при этом надлежащую гигиену монитора.

1ф 21в проверка приведения vAA, type@BBBB A: регистр ссылки (8 бит).
B: индекс типа (16 бит)
Вызовите ClassCastException , если ссылку в данном регистре невозможно привести к указанному типу.

Примечание. Поскольку A всегда должно быть ссылкой (а не примитивным значением), это обязательно завершится ошибкой во время выполнения (то есть выдаст исключение), если B ссылается на примитивный тип.

20 22в экземпляр vA, vB, type@CCCC A: регистр назначения (4 бита)
B: регистр ссылки (4 бита).
C: индекс типа (16 бит)
Сохраните в данном регистре назначения 1 , если указанная ссылка является экземпляром данного типа, или 0 если нет.

Примечание. Поскольку B всегда должно быть ссылкой (а не примитивным значением), это всегда приведет к сохранению 0 , если C ссылается на примитивный тип.

21 12x длина массива vA, vB A: регистр назначения (4 бита)
B: регистр ссылки на массив (4 бита).
Сохраните в данном регистре назначения длину указанного массива в записях.
22 21с новый экземпляр vAA, тип@BBBB A: регистр назначения (8 бит)
B: индекс типа
Создайте новый экземпляр указанного типа, сохранив ссылку на него в месте назначения. Тип должен ссылаться на класс, не являющийся массивом.
23 22в новый массив vA, vB, type@CCCC A: регистр назначения (4 бита)
B: регистр размера
C: индекс типа
Создайте новый массив указанного типа и размера. Тип должен быть типом массива.
24 35с заполненный новый массив {vC, vD, vE, vF, vG}, type@BBBB A: размер массива и количество слов аргумента (4 бита).
B: индекс типа (16 бит)
C..G: регистры аргументов (по 4 бита каждый)
Создайте массив заданного типа и размера, заполнив его предоставленным содержимым. Тип должен быть типом массива. Содержимое массива должно состоять из одного слова (т. е. нельзя использовать массивы типа long или double , но допустимы ссылочные типы). Сконструированный экземпляр сохраняется как «результат» точно так же, как инструкции вызова метода сохраняют свои результаты, поэтому сконструированный экземпляр необходимо переместить в регистр с немедленной последующей инструкцией move-result-object (если она будет использоваться ).
25 3рц заполненный-новый-массив/диапазон {vCCCC .. vNNNN}, type@BBBB A: размер массива и количество слов аргумента (8 бит).
B: индекс типа (16 бит)
C: регистр первого аргумента (16 бит).
N = A + C - 1
Создайте массив заданного типа и размера, заполнив его предоставленным содержимым. Пояснения и ограничения такие же, как filled-new-array , описанного выше.
26 31т fill-array-data vAA, +BBBBBBBB (с дополнительными данными, как указано ниже в «Формате fill-array-data-payload ») A: ссылка на массив (8 бит)
B: смещение "ветви" со знаком для псевдоинструкции табличных данных (32 бита).
Заполните данный массив указанными данными. Ссылка должна быть на массив примитивов, а таблица данных должна соответствовать ей по типу и содержать не больше элементов, чем поместится в массиве. То есть массив может быть больше таблицы, и в этом случае устанавливаются только начальные элементы массива, а остальные остаются.
27 11x бросить ваа A: регистр, несущий исключения (8 бит).
Выдать указанное исключение.
28 10т перейти к +АА A: смещение ветки со знаком (8 бит). Безоговорочный переход к указанной инструкции.

Примечание. Смещение ветки не должно быть 0 . (Спин-цикл может быть законно создан либо с помощью goto/32 , либо путем включения nop в качестве цели перед переходом.)

29 20т перейти к/16 +AAAA A: смещение ветки со знаком (16 бит).
Безоговорочный переход к указанной инструкции.

Примечание. Смещение ветки не должно быть 0 . (Спин-цикл может быть законно создан либо с помощью goto/32 , либо путем включения nop в качестве цели перед переходом.)

2а 30т перейти к/32 +АААААААА A: смещение ветки со знаком (32 бита)
Безоговорочный переход к указанной инструкции.
2б 31т vAA с упакованным коммутатором, +BBBBBBBB (с дополнительными данными, указанными ниже в «Формате packed-switch-payload ») A: зарегистрируйтесь для тестирования
B: смещение "ветви" со знаком для псевдоинструкции табличных данных (32 бита).
Перейдите к новой инструкции на основе значения в данном регистре, используя таблицу смещений, соответствующую каждому значению в определенном целочисленном диапазоне, или перейдите к следующей инструкции, если совпадений нет.
2с 31т разреженный коммутатор vAA, +BBBBBBBB (с дополнительными данными, как указано ниже в «Формате sparse-switch-payload ») A: зарегистрируйтесь для тестирования
B: смещение "ветви" со знаком для псевдоинструкции табличных данных (32 бита).
Перейдите к новой инструкции на основе значения в данном регистре, используя упорядоченную таблицу пар значение-смещение, или перейдите к следующей инструкции, если совпадений нет.
2д..31 23x вид cmp vAA, vBB, vCC
2d: cmpl-float (смещение lt)
2e: cmpg-float (смещение gt)
2f: cmpl-double (LT-смещение)
30: cmpg-double (смещение gt)
31: см-длина
A: регистр назначения (8 бит)
B: первый исходный регистр или пара
C: второй исходный регистр или пара
Выполните указанное сравнение с плавающей запятой или long сравнение, установив a равным 0 , если b == c , 1 если b > c , или -1 если b < c . «Смещение», указанное для операций с плавающей запятой, указывает, как обрабатываются сравнения NaN : инструкции «gt смещения» возвращают 1 для сравнений NaN , а инструкции «lt смещения» возвращают -1 .

Например, чтобы проверить, является ли плавающая точка x < y рекомендуется использовать cmpg-float ; результат -1 указывает, что тест был истинным, а другие значения указывают, что он был ложным либо из-за допустимого сравнения, либо из-за того, что одно из значений было NaN .

32..37 22т if- тест vA, vB, +CCCC
32: если-экв
33: если-не
34: если-lt
35: если-ге
36: если-гт
37: если-ле
A: первый регистр для проверки (4 бита)
B: второй регистр для проверки (4 бита)
C: смещение ветки со знаком (16 бит).
Переход к заданному месту назначения, если значения данных двух регистров сравниваются указанным образом.

Примечание. Смещение ветки не должно быть 0 . (Спин-цикл может быть законно построен либо путем ветвления вокруг обратного goto , либо путем включения nop в качестве цели перед ветвлением.)

38..3д 21т if- тест z vAA, +BBBB
38: если-eqz
39: если-нез
3а: если-ltz
3б: если-гез
3c: если-гтц
3d: если-лез
A: зарегистрируйтесь для тестирования (8 бит)
B: смещение ветки со знаком (16 бит)
Переход к заданному месту назначения, если значение данного регистра сравнивается с 0, как указано.

Примечание. Смещение ветки не должно быть 0 . (Спин-цикл может быть законно построен либо путем ветвления вокруг обратного goto , либо путем включения nop в качестве цели перед ветвлением.)

3e..43 10x (не используется) (не используется)
44..51 23x массив vAA, vBB, vCC
44: получить
45: общий
46: объект-get
47: логическое значение
48: get-байт
49: get-char
4a: короткое замыкание
4б: апут
4c: по всей длине
4d: апут-объект
4e: логическое значение aput
4f: входной байт
50: апут-символ
51: апут-короткий
A: регистр значений или пара; может быть источником или приемником (8 бит)
B: регистр массива (8 бит)
C: индексный регистр (8 бит)
Выполнить операцию с идентифицированным массивом по идентифицированному индексу данного массива, загрузив или сохранив в регистр значений.
52..5f 22c я экземпляр vA, vB, field@CCCC
52: получить
53: широкий
54: iget-объект
55: iget-логическое значение
56: iget-байт
57: iget-char
58: короткое замыкание
59: вход
5a: весь IP-вход
5b: iput-объект
5c: логическое значение ввода
5d: входной байт
5e: iput-char
5f: короткое замыкание ввода
A: регистр значений или пара; может быть источником или приемником (4 бита)
B: регистр объекта (4 бита)
C: индекс ссылки на поле экземпляра (16 бит).
Выполните операцию с полем экземпляра идентифицированного объекта с идентифицированным полем, загрузив или сохранив его в регистр значений.

Примечание. Эти коды операций являются разумными кандидатами для статического связывания, изменяя аргумент поля на более прямое смещение.

60..6д 21в s staticop vAA, поле@BBBB
60: Сгет
61: широкий охват
62: sget-объект
63: логическое значение
64: Sget-байт
65: sget-символ
66: короткий
67: тыр
68: по всей длине
69: спутник-объект
6a: логическое значение
6b: выходной байт
6c: sput-символ
6d: короткое замыкание
A: регистр значений или пара; может быть источником или приемником (8 бит)
B: индекс ссылки на статическое поле (16 бит).
Выполнить операцию статического поля идентифицированного объекта с идентифицированным статическим полем, загрузив или сохранив его в регистр значений.

Примечание. Эти коды операций являются разумными кандидатами для статического связывания, изменяя аргумент поля на более прямое смещение.

6э..72 35в вызов- вид {vC, vD, vE, vF, vG}, meth@BBBB
6e: вызвать виртуальный
6f: вызвать-супер
70: прямой вызов
71: вызвать статический
72: вызвать-интерфейс
A: количество слов аргумента (4 бита)
B: индекс ссылки на метод (16 бит).
C..G: регистры аргументов (по 4 бита каждый)
Вызовите указанный метод. Результат (если таковой имеется) может быть сохранен с соответствующим вариантом move-result* в качестве следующей инструкции.

invoke-virtual используется для вызова обычного виртуального метода (метода, который не является private , static или final , а также не является конструктором).

Когда method_id ссылается на метод неинтерфейсного класса, invoke-super используется для вызова виртуального метода ближайшего суперкласса (в отличие от метода с тем же method_id в вызывающем классе). Действуют те же ограничения на метод, что и для invoke-virtual .

В файлах Dex версии 037 или более поздней, если method_id относится к методу интерфейса, invoke-super используется для вызова наиболее конкретной, непереопределенной версии этого метода, определенной в этом интерфейсе. Действуют те же ограничения на метод, что и для invoke-virtual . В файлах Dex до версии 037 наличие интерфейса method_id является незаконным и неопределенным.

invoke-direct используется для вызова static прямого метода (то есть метода экземпляра, который по своей природе не является переопределяемым, а именно либо private метода экземпляра, либо конструктора).

invoke-static используется для вызова static метода (который всегда считается прямым методом).

invoke-interface используется для вызова метода interface , то есть для объекта, конкретный класс которого неизвестен, с использованием method_id , который ссылается на interface .

Примечание. Эти коды операций являются разумными кандидатами для статического связывания, изменяя аргумент метода на более прямое смещение (или его пару).

73 10x (не используется) (не используется)
74..78 3ср вызов- вид /диапазон {vCCCC .. vNNNN}, meth@BBBB
74: вызвать-виртуальный/диапазон
75: вызвать-супер/диапазон
76: вызвать-прямой/диапазон
77: вызвать-статический/диапазон
78: вызвать-интерфейс/диапазон
A: количество слов аргумента (8 бит).
B: индекс ссылки на метод (16 бит).
C: регистр первого аргумента (16 бит).
N = A + C - 1
Вызовите указанный метод. Подробности, предостережения и предложения см. выше в описании первого invoke- kind .
79..7а 10х (не используется) (не используется)
7б..8е 12х уноп ва, вб
7b: отрицание-целое
7c: не целое
7d: нег-длинный
7e: недолго
7f: отрицательное число с плавающей запятой
80: нег-двойной
81: от целого к длинному
82: целое число с плавающей запятой
83: инт-дабл
84: длинное до целого
85: долго плавать
86: длинная ставка на удвоение
87: число с плавающей запятой
88: плавающее к длинному
89: число с плавающей точкой в ​​двойное
8a: двойной-целый
8b: двойной-длинный
8c: двойной с плавающей запятой
8d: целое число в байт
8e: int-to-char
8f: от целого к короткому
A: регистр назначения или пара (4 бита).
B: исходный регистр или пара (4 бита).
Выполните указанную унарную операцию с исходным регистром, сохранив результат в регистре назначения.
90..af 23x биноп vAA, vBB, vCC
90: надстройка
91: субинт
92: многоцелевой
93: div-int
94: рем-инт
95: и-инт
96: или-целое
97: xor-int
98: шл-инт
99: шр-инт
9а: ушр-инт
9b: добавить длину
9c: почти длинный
9д: многодлинный
9e: длина div
9f: рем-длинный
a0: и-длинный
a1: или-длинный
a2: xor-long
a3: shl-длинный
а4: шр-длинный
a5: ушр-длинный
a6: добавить плавающее число
a7: суб-плавающее
a8: несколько с плавающей запятой
a9: div-float
аа: rem-float
ab: добавить двойной
переменный ток: суб-дабл
объявление: мульти-дабл
ae: div-double
аф: рем-дабл
A: регистр назначения или пара (8 бит).
B: первый исходный регистр или пара (8 бит).
C: второй исходный регистр или пара (8 бит).
Выполните указанную двоичную операцию над двумя исходными регистрами, сохранив результат в регистре назначения.

Примечание. В отличие от других математических операций -long (которые принимают пары регистров как в качестве первого, так и в качестве второго источника), shl-long , shr-long и ushr-long принимают пару регистров в качестве первого источника (значение, которое нужно сдвинуть). ), но один регистр для их второго источника (расстояние сдвига).

b0..cf 12x биноп /2адрес вА, ВБ
b0: надстройка/2адрес
b1: субинтервал/2адрес
b2: множественное число/2адрес
b3: div-int/2адрес
b4: рем-интервал/2адрес
b5: и-int/2адрес
b6: или-int/2адрес
b7: xor-int/2адрес
b8: shl-int/2адрес
b9: shr-int/2адрес
ба: ushr-int/2addr
bb: добавить-длинный/2адрес
bc: субдлинный/2адрес
BD: mul-long/2addr
быть: div-long/2addr
bf: rem-long/2addr
c0: и-длинный/2адрес
c1: или-длинный/2адрес
c2: xor-long/2addr
c3: shl-long/2addr
c4: shr-long/2addr
c5: ushr-long/2addr
c6: добавить-с плавающей запятой/2адрес
c7: субфлоат/2адрес
c8: mul-float/2addr
c9: div-float/2адрес
ca: rem-float/2addr
cb: добавить-двойной/2адрес
копия: суб-двойной/2адрес
компакт-диск: mul-double/2addr
ce: div-double/2addr
ср: rem-double/2addr
A: регистр назначения и первый источник или пара (4 бита).
B: второй исходный регистр или пара (4 бита).
Выполните указанную двоичную операцию над двумя исходными регистрами, сохранив результат в первом исходном регистре.

Примечание. В отличие от других математических операций -long/2addr (которые принимают пары регистров как для пункта назначения/первого источника, так и для второго источника), shl-long/2addr , shr-long/2addr и ushr-long/2addr принимают регистр. пара для их пункта назначения/первого источника (значение, подлежащее сдвигу), но один регистр для их второго источника (расстояние сдвига).

d0..d7 22с binop /lit16 vA, vB, #+CCCC
d0: надстройка/lit16
d1: rsub-int (обратное вычитание)
d2: мультиинт/лит16
d3: div-int/lit16
d4: рем-инт/лит16
d5: и-int/lit16
d6: или-int/lit16
d7: xor-int/lit16
A: регистр назначения (4 бита)
B: исходный регистр (4 бита)
C: константа int со знаком (16 бит)
Выполните указанную двоичную операцию с указанным регистром (первый аргумент) и литеральным значением (второй аргумент), сохранив результат в регистре назначения.

Примечание: rsub-int нет суффикса, поскольку эта версия является основным кодом операции своего семейства. Также см. ниже подробную информацию о его семантике.

d8..e2 22b биноп /лит8 вАА, вББ, #+CC
d8: надстройка/lit8
d9: rsub-int/lit8
да: mul-int/lit8
БД: div-int/lit8
постоянный ток: рем-int/lit8
дд: и-int/lit8
де: или-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: shr-int/lit8
e2: ушр-int/lit8
A: регистр назначения (8 бит)
B: исходный регистр (8 бит)
C: константа int со знаком (8 бит)
Выполните указанную двоичную операцию с указанным регистром (первый аргумент) и литеральным значением (второй аргумент), сохранив результат в регистре назначения.

Примечание. Подробную информацию о семантике rsub-int см. ниже.

e3..f9 10x (не используется) (не используется)
фа 45cc вызов-полиморфный {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: количество слов аргумента (4 бита)
B: индекс ссылки на метод (16 бит).
C: приемник (4 бита)
D..G: регистры аргументов (по 4 бита каждый)
H: эталонный индекс прототипа (16 бит)
Вызовите указанный полиморфный метод подписи. Результат (если таковой имеется) может быть сохранен с соответствующим вариантом move-result* в качестве следующей инструкции.

Ссылка на метод должна указывать на сигнатурный полиморфный метод, например java.lang.invoke.MethodHandle.invoke или java.lang.invoke.MethodHandle.invokeExact .

Получатель должен быть объектом, поддерживающим вызываемый метод полиморфной подписи.

Ссылка на прототип описывает предоставленные типы аргументов и ожидаемый тип возвращаемого значения.

invoke-polymorphic может вызывать исключения при выполнении. Исключения описаны в документации API для вызываемого метода полиморфной подписи.

Присутствует в файлах Dex, начиная с версии 038 .
фб 4rcc вызов-полиморфный/диапазон {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: количество слов аргумента (8 бит).
B: индекс ссылки на метод (16 бит).
C: приемник (16 бит)
H: эталонный индекс прототипа (16 бит)
N = A + C - 1
Вызовите указанный дескриптор метода. Подробности смотрите в описании invoke-polymorphic выше.

Присутствует в файлах Dex, начиная с версии 038 .
ФК 35с вызвать-пользовательский {vC, vD, vE, vF, vG}, call_site@BBBB A: количество слов аргумента (4 бита)
B: индекс ссылки на сайт вызова (16 бит)
C..G: регистры аргументов (по 4 бита каждый)
Разрешает и вызывает указанный сайт вызова. Результат вызова (если таковой имеется) может быть сохранен с соответствующим вариантом move-result* в качестве следующей инструкции.

Эта инструкция выполняется в два этапа: разрешение узла вызова и вызов узла вызова.

Разрешение сайта вызова проверяет, имеет ли указанный сайт вызова связанный экземпляр java.lang.invoke.CallSite . В противном случае метод компоновщика начальной загрузки для указанного сайта вызова вызывается с использованием аргументов, присутствующих в файле DEX (см. call_site_item ). Метод компоновщика начальной загрузки возвращает экземпляр java.lang.invoke.CallSite , который затем будет связан с указанным сайтом вызова, если ассоциации не существует. Другой поток, возможно, уже выполнил ассоциацию первым, и в этом случае выполнение инструкции продолжается с первым связанным экземпляром java.lang.invoke.CallSite .

Вызов сайта вызова выполняется для целевого объекта java.lang.invoke.MethodHandle разрешенного экземпляра java.lang.invoke.CallSite . Цель вызывается так же, как если бы выполнялся invoke-polymorphic (описанный выше) с использованием дескриптора метода и аргументов invoke-custom инструкции вызова в качестве аргументов для точного вызова дескриптора метода.

Исключения, возникающие методом компоновщика начальной загрузки, заключаются в java.lang.BootstrapMethodError . Ошибка BootstrapMethodError также возникает, если:
  • метод компоновщика начальной загрузки не может вернуть экземпляр java.lang.invoke.CallSite .
  • возвращенный java.lang.invoke.CallSite имеет null цель дескриптора метода.
  • цель дескриптора метода не относится к запрошенному типу.
Присутствует в файлах Dex, начиная с версии 038 .
ФД 3RC вызвать-custom/диапазон {vCCCC .. vNNNN}, call_site@BBBB A: количество слов аргумента (8 бит).
B: индекс ссылки на сайт вызова (16 бит)
C: регистр первого аргумента (16 бит).
N = A + C - 1
Разрешите и вызовите сайт вызова. Подробности смотрите в описании invoke-custom выше.

Присутствует в файлах Dex, начиная с версии 038 .
фе 21с const-method-handle vAA, метод_handle@BBBB A: регистр назначения (8 бит)
B: индекс дескриптора метода (16 бит)
Переместите ссылку на дескриптор метода, указанный данным индексом, в указанный регистр.

Присутствует в файлах Dex, начиная с версии 039 .
фф 21с тип константного метода vAA, proto@BBBB A: регистр назначения (8 бит)
B: ссылка на прототип метода (16 бит).
Переместите ссылку на прототип метода, указанный данным индексом, в указанный регистр.

Присутствует в файлах Dex, начиная с версии 039 .

формат полезной нагрузки упакованного переключателя

Имя Формат Описание
личность ушорт = 0x0100 идентификация псевдооперационного кода
размер сокращать количество записей в таблице
первый_ключ интервал первое (и наименьшее) значение регистра переключателя
цели интервал [] список целей относительной ветки size . Цели относятся к адресу кода операции переключения, а не к этой таблице.

Примечание. Общее количество единиц кода для экземпляра этой таблицы равно (size * 2) + 4 .

формат полезной нагрузки разреженного переключателя

Имя Формат Описание
личность ушорт = 0x0200 идентификация псевдооперационного кода
размер сокращать количество записей в таблице
ключи интервал [] список значений ключей size , отсортированных по возрастанию
цели интервал [] список целей относительной ветки size , каждая из которых соответствует значению ключа в том же индексе. Цели относятся к адресу кода операции переключения, а не к этой таблице.

Примечание. Общее количество единиц кода для экземпляра этой таблицы равно (size * 4) + 2 .

формат полезной нагрузки fill-array-data

Имя Формат Описание
личность ушорт = 0x0300 идентификация псевдооперационного кода
element_width сокращать количество байтов в каждом элементе
размер uint количество элементов в таблице
данные убайт[] значения данных

Примечание. Общее количество единиц кода для экземпляра этой таблицы равно (size * element_width + 1) / 2 + 4 .

Детали математических операций

Примечание. Операции с плавающей запятой должны соответствовать правилам IEEE 754, используя округление до ближайшего и постепенное уменьшение значения, если не указано иное.

Код операции Семантика Си Примечания
отрицательный-целый int32 а;
int32 результат = -а;
Унарное дополнение до двух.
не-int int32 а;
int32 результат = ~а;
Унарные-дополняющие.
нег-длинный int64 а;
int64 результат = -а;
Унарное дополнение до двух.
недолго int64 а;
int64 результат = ~а;
Унарные-дополняющие.
отрицательное число с плавающей запятой плавать а;
результат с плавающей запятой = -а;
Отрицание с плавающей запятой.
отрицательный двойной двойная а;
двойной результат = -а;
Отрицание с плавающей запятой.
Int-to-Long Int32 A;
int64 result = (int64) a;
Удлинитель знака int32 в int64 .
Int-to-Float Int32 A;
float result = (float) a;
Преобразование int32 в float , используя круглую до ближайшего. Это теряет точность для некоторых значений.
Int-Double Int32 A;
двойной результат = (двойной) a;
Преобразование int32 в double .
Длинный и инт Int64 A;
int32 result = (int32) a;
Усечение int64 в int32 .
ДЛЯ ДЛЯ ПЕРЕХОВАНИЯ Int64 A;
float result = (float) a;
Преобразование int64 в float , используя круглую до ближайшего. Это теряет точность для некоторых значений.
долго-удробление Int64 A;
двойной результат = (двойной) a;
Преобразование int64 в double , используя круглую до ближайшего. Это теряет точность для некоторых значений.
поплавковой Плавать А;
int32 result = (int32) a;
Преобразование float в int32 , используя круглую товард-нулевой. NaN и -0.0 (отрицательный ноль) конвертируются в целое число 0 . Бесконечности и значения с слишком большой величиной, которая должна быть представлена, преобразуются в 0x7fffffff или -0x80000000 в зависимости от знака.
поплавок к длину Плавать А;
int64 result = (int64) a;
Преобразование float в int64 , используя круглую товард-нулевой. Те же самые специальные правила случая, что и для float-to-int применяются здесь, за исключением того, что значения вне диапазона конвертируются в 0x7fffffffffffffff или -0x8000000000000000 в зависимости от знака.
поплавок к-удвоению Плавать А;
двойной результат = (двойной) a;
Преобразование float в double , сохраняя значение точно.
двойной до наступления двойная а;
int32 result = (int32) a;
Преобразование double в int32 , используя круглую товард-норно. Те же самые специальные правила случая, что и для float-to-int применяются здесь.
двойной до длины двойная а;
int64 result = (int64) a;
Преобразование double в int64 , используя круглую товард-нулевой. Те же самые специальные правила, что и для float-to-long применяются здесь.
двойной до распыления двойная а;
float result = (float) a;
Преобразование double в float , используя круглую до ближайшего. Это теряет точность для некоторых значений.
Int-Byte Int32 A;
int32 result = (a << 24) >> 24;
Усечение int32 до int8 , знак, расширяющий результат.
Int-to-Char Int32 A;
int32 result = a & 0xffff;
Усечение int32 до uint16 , без удлинения знаков.
int-to-short Int32 A;
int32 result = (a << 16) >> 16;
Усечение int32 до int16 , знак, расширяющий результат.
add-int Int32 A, B;
int32 result = a + b;
Двойное дополнение.
суб Int32 A, B;
int32 result = a - b;
Вычитание с двойным комплексом.
rsub-int Int32 A, B;
int32 result = b - a;
Двойное содействие обратной вычитании.
mul-int Int32 A, B;
int32 result = a * b;
Умножение двойного комплекса.
div-int Int32 A, B;
int32 result = a / b;
Разделение двойного комплекта, округленное к нулю (то есть усеченное до целочисленного). Это бросает ArithmeticException если b == 0 .
Rem-int Int32 A, B;
int32 result = a % b;
ДВО-СООБЩЕНИЕ СЛОЖЕТ ПОСЛЕДНИЙ ДИСПЕРКИ. Знак результата такой же, как и у a , и он более точно определяется как result == a - (a / b) * b . Это бросает ArithmeticException если b == 0 .
и int Int32 A, B;
int32 result = a & b;
Побито и.
или кисть Int32 A, B;
int32 result = a | б;
Кубик или.
xor-int Int32 A, B;
int32 result = a ^ b;
Побитовый XOR.
Shl-int Int32 A, B;
int32 result = a << (b & 0x1f);
Полезно сдвиг (с аргументом в масках).
shr-int Int32 A, B;
int32 result = a >> (b & 0x1f);
Bitwase подписано смены справа (с аргументом в масках).
ushr-int Uint32 A, B;
int32 result = a >> (b & 0x1f);
Bitwise Unsigned Shift Right (с аргументом в масках).
Добавить Int64 A, B;
int64 result = a + b;
Двойное дополнение.
подконец Int64 A, B;
int64 result = a - b;
Вычитание с двойным комплексом.
Mul-Long Int64 A, B;
int64 result = a * b;
Умножение двойного комплекса.
Div-Long Int64 A, B;
int64 result = a / b;
Разделение двойного комплекта, округленное к нулю (то есть усеченное до целочисленного). Это бросает ArithmeticException если b == 0 .
Rem-Long Int64 A, B;
int64 результат = A % b;
ДВО-СООБЩЕНИЕ СЛОЖЕТ ПОСЛЕДНИЙ ДИСПЕРКИ. Знак результата такой же, как и у a , и он более точно определяется как result == a - (a / b) * b . Это бросает ArithmeticException если b == 0 .
и долго Int64 A, B;
int64 result = a & b;
Побито и.
или длинный Int64 A, B;
int64 result = a | б;
Кубик или.
XOR-Long Int64 A, B;
int64 result = a ^ b;
Побитовый XOR.
SHL-Long Int64 A;
Int32 B;
int64 result = a << (b & 0x3f);
Полезно сдвиг (с аргументом в масках).
shr-long Int64 A;
Int32 B;
int64 result = a >> (b & 0x3f);
Bitwase подписано смены справа (с аргументом в масках).
USHR-Long Uint64 A;
Int32 B;
int64 result = a >> (b & 0x3f);
Bitwise Unsigned Shift Right (с аргументом в масках).
Дополнение Float A, B;
float result = a + b;
Дополнение плавающей запятой.
суб-распах Float A, B;
float result = a - b;
Вычитание с плавающей запятой.
Mul-Float Float A, B;
float result = a * b;
Умножение плавающей точки.
div-float Float A, B;
float result = a / b;
Подразделение с плавающей запятой.
Rem-Float Float A, B;
Результат плавания = A % B;
Остаток плавающей запятой после деления. Эта функция отличается от оставшейся части IEEE 754 и определяется как result == a - roundTowardZero(a / b) * b .
Добавить удвоить двойной a, b;
двойной результат = a + b;
Дополнение плавающей запятой.
суб-удвоение двойной a, b;
двойной результат = a - b;
Вычитание с плавающей запятой.
Mul-Double двойной a, b;
двойной результат = a * b;
Умножение плавающей точки.
Div-Double двойной a, b;
двойной результат = A / B;
Подразделение с плавающей запятой.
Rem-Double двойной a, b;
двойной результат = a % b;
Остаток плавающей запятой после деления. Эта функция отличается от оставшейся части IEEE 754 и определяется как result == a - roundTowardZero(a / b) * b .