Байт-код Dalvik

Общий дизайн

  • Модель машины и соглашения о вызовах предназначены для приблизительной имитации общих реальных архитектур и соглашений о вызовах в стиле C:
    • Машина основана на регистрах, а размеры кадров фиксируются при создании. Каждый кадр состоит из определенного количества регистров (указанного методом), а также любых дополнительных данных, необходимых для выполнения метода, таких как (но не ограничиваясь ими) программный счетчик и ссылка на файл .dex , содержащий метод. .
    • При использовании для битовых значений (таких как целые числа и числа с плавающей запятой) регистры считаются 32-битными. Смежные пары регистров используются для 64-битных значений. Для пар регистров не требуется выравнивания.
    • При использовании для ссылок на объекты регистры считаются достаточно широкими, чтобы содержать ровно одну такую ​​ссылку.
    • С точки зрения побитового представления (Object) null == (int) 0 .
    • N аргументов метода помещаются в последние N регистров кадра вызова метода по порядку. Широкие аргументы занимают два регистра. Методы экземпляра передаются по ссылке this в качестве первого аргумента.
  • Единицей памяти в потоке команд является 16-битная беззнаковая величина. Некоторые биты в некоторых инструкциях игнорируются/должны быть равны нулю.
  • Инструкции не ограничиваются безвозмездно определенным типом. Например, инструкции, которые перемещают 32-битные значения регистров без интерпретации, не должны указывать, перемещают ли они целые числа или числа с плавающей запятой.
  • Существуют отдельно перечисляемые и индексируемые пулы констант для ссылок на строки, типы, поля и методы.
  • Побитовые литеральные данные представлены в потоке инструкций.
  • Поскольку на практике для метода редко требуется более 16 регистров, а потребность в более чем восьми регистрах достаточно распространена, многие инструкции ограничиваются адресацией только первых 16 регистров. Когда это разумно возможно, инструкции позволяют обращаться к первым 256 регистрам. Кроме того, у некоторых инструкций есть варианты, которые позволяют использовать гораздо большее количество регистров, включая пару универсальных инструкций move , которые могут обращаться к регистрам в диапазоне от v0 v65535 . В тех случаях, когда вариант инструкции недоступен для обращения к нужному регистру, ожидается, что содержимое регистра будет перемещено из исходного регистра в младший регистр (перед операцией) и/или перемещено из младшего результирующего регистра в старший. зарегистрироваться (после операции).
  • Существует несколько «псевдоинструкций», которые используются для хранения полезных данных переменной длины, на которые ссылаются обычные инструкции (например, 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 » — исходный регистр, который должен находиться в диапазоне от v0 v65535 .
  • См. документ форматов инструкций для получения более подробной информации о различных форматах инструкций (перечисленных в разделе «Операция и формат»), а также сведения о синтаксисе кода операции.
  • См. документ о формате файла .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 vAAAA, vBBBB 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а 11х ход-результат vAA A: регистр назначения (8 бит) Переместите однословный необъектный результат самого последнего invoke- kind в указанный регистр. Это должно быть сделано в виде инструкции сразу после invoke- kind , чей результат (одно слово, не объект) не должен игнорироваться; где-либо еще является недействительным.
0b 11x vAA для всего результата перемещения A: пара регистров назначения (8 бит) Переместите двойное слово результата самого последнего invoke- kind в указанную пару регистров. Это должно быть сделано как инструкция сразу после invoke- kind , результат которого (двойное слово) не должен игнорироваться; где-либо еще является недействительным.
0с 11х объект-результат перемещения vAA A: регистр назначения (8 бит) Переместите результат объекта самого последнего invoke- kind в указанный регистр. Это должно быть сделано как инструкция сразу после invoke- kind или filled-new-array , чей результат (объект) не должен игнорироваться; где-либо еще является недействительным.
0д 11х движение-исключение vAA A: регистр назначения (8 бит) Сохранить только что перехваченное исключение в указанный регистр. Это должна быть первая инструкция любого обработчика исключений, чье пойманное исключение не должно игнорироваться, и эта инструкция должна когда-либо появляться только как первая инструкция обработчика исключений; где-либо еще является недействительным.
0e 10x возврат-недействительность Возврат из метода void .
0f 11x вернуть vAA A: регистр возвращаемого значения (8 бит) Возврат из метода одинарной ширины (32-разрядного) без объекта, возвращающего значение.
10 11x vAA для всего возврата A: возвращаемое значение регистр-пара (8 бит) Возврат из метода, возвращающего значение двойной ширины (64 бита).
11 11x возвращаемый объект vAA A: регистр возвращаемого значения (8 бит) Возврат из метода, возвращающего объект.
12 11н const/4 vA, #+B A: регистр назначения (4 бита)
B: целое число со знаком (4 бита)
Переместите заданное литеральное значение (расширенное по знаку до 32 бит) в указанный регистр.
13 21с const/16 vAA, #+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л const-wide 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 бит) Приобретите монитор для указанного объекта.
1е 11х монитор-выход 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 +AAAAAAAA A: смещение ветви со знаком (32 бита)
Безоговорочный переход к указанной инструкции.
2б 31т упакованный коммутатор vAA, +BBBBBBBB (с дополнительными данными, как указано ниже в «формате packed-switch-payload ») A: зарегистрироваться для тестирования
B: подписанное смещение «ветви» к псевдоинструкции табличных данных (32 бита)
Перейти к новой инструкции на основе значения в данном регистре, используя таблицу смещений, соответствующих каждому значению в определенном диапазоне интегралов, или перейти к следующей инструкции, если совпадения нет.
2с 31т sparse-switch vAA, +BBBBBBBB (с дополнительными данными, указанными ниже в «формате sparse-switch-payload ») A: зарегистрироваться для тестирования
B: подписанное смещение «ветви» к псевдоинструкции табличных данных (32 бита)
Перейти к новой инструкции на основе значения в данном регистре, используя упорядоченную таблицу пар значение-смещение, или перейти к следующей инструкции, если совпадения нет.
2д..31 23х тип cmp vAA, vBB, vCC
2d: cmpl-float (смещение lt)
2e: cmpg-float (смещение gt)
2f: cmpl-двойной (низкий уклон)
30: cmpg-double (уклон gt)
31: cmp-длинный
A: регистр назначения (8 бит)
B: первый исходный регистр или пара
C: второй исходный регистр или пара
Выполните указанное сравнение с плавающей запятой или long сравнение, установив a в 0 , если b == c , 1 , если b > c , или -1 , если b < c . «Смещение», указанное для операций с плавающей запятой, указывает, как обрабатываются сравнения NaN : инструкции «gtbias» возвращают 1 для сравнений NaN , а инструкции «ltbias» возвращают -1 .

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

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

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

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

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

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

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

60..6д 21с s staticop vAA, field@BBBB
60: сгет
61: широкий
62: sget-объект
63: sget-логическое значение
64: sget-байт
65: sget-char
66: короткий
67: тыр
68: ширина носа
69: развед-объект
6a: sput-boolean
6b: sput-byte
6c: sput-char
6д: спут-короткая
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х unop vA , vB
7b: отрицательное целое
7c: не-инт
7d: отрицательная длинна
7e: недолго
7f: отрицательный с плавающей запятой
80: отрицательный двойной
81: от целого к длинному
82: in-to-float
83: инт-в-дабл
84: длинное в целое
85: долго плавающий
86: длинный-удвоить
87: число с плавающей запятой
88: с плавающей запятой
89: число с плавающей запятой
8a: двойное целое
8b: двойной к длинному
8c: двойное плавание
8d: int-to-byte
8e: int-to-char
8f: инт-к-короткому
A: регистр назначения или пара (4 бита)
B: исходный регистр или пара (4 бита)
Выполните идентифицированную унарную операцию в исходном регистре, сохранив результат в целевом регистре.
90..af 23x биноп vAA, vBB, vCC
90: надстройка
91: субинт
92: многоцелевое
93: деление-целое
94: остаток-инт
95: и-инт
96: или-целое
97: xor-int
98: шл-инт
99: шр-инт
9а: ушр-инт
9b: добавить долго
9c: субдлинный
9d: мул-лонг
9e: длинный раздел
9f: rem-длинный
a0: и-длинный
a1: или-длинный
a2: xor-лонг
a3: з/д
a4: шр-длинный
a5: ушр - длинная
a6: добавить с плавающей запятой
a7: вспомогательный поплавок
a8: множественное число с плавающей запятой
a9: деление с плавающей запятой
aa: rem-поплавок
аб: добавить-двойной
переменный ток: саб-дабл
объявление: мул-дабл
ae: div-двойной
af: rem-двойной
A: регистр назначения или пара (8 бит)
B: первый исходный регистр или пара (8 бит)
C: второй исходный регистр или пара (8 бит)
Выполните идентифицированную двоичную операцию над двумя исходными регистрами, сохранив результат в целевом регистре.

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

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

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

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

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

d8..e2 22b binop /lit8 vAA, vBB, #+CC
d8: добавить int/lit8
d9: rsub-int/lit8
da: mul-int/lit8
БД: div-int/lit8
постоянный ток: rem-int/lit8
дд: и-инт/лит8
de: or-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: шр-инт/лит8
e2: ushr-int/lit8
A: регистр назначения (8 бит)
B: исходный регистр (8 бит)
C: целочисленная константа со знаком (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 .
фб 4ркк вызывать-полиморфный/диапазон {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 пользовательский вызов/диапазон {vCCCC .. vNNNN}, call_site@BBBB A: количество слов аргумента (8 бит)
B: индекс ссылки на сайт вызова (16 бит)
C: регистр первого аргумента (16 бит)
N = A + C - 1
Разрешите и вызовите сайт вызова. Подробности смотрите в описании invoke-custom выше.

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

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

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

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

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

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

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

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

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

формат заполнения-массива-данных-полезной нагрузки

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

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

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

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

Опкод Си Семантика Заметки
отрицательный интервал int32 а;
результат int32 = -а;
Унарное дополнение до двух.
не-инт int32 а;
int32 результат = ~а;
Унарные единицы-дополнение.
отрицательный int64 а;
результат int64 = -а;
Унарное дополнение до двух.
недолго int64 а;
int64 результат = ~ а;
Унарные единицы-дополнение.
отрицательный с плавающей запятой плавать а;
результат с плавающей запятой = -a;
Floating point negation.
neg-double double a;
double result = -a;
Floating point negation.
int-to-long int32 a;
int64 result = (int64) a;
Sign extension of int32 into int64 .
int-to-float int32 a;
float result = (float) a;
Conversion of int32 to float , using round-to-nearest. This loses precision for some values.
int-to-double int32 a;
double result = (double) a;
Conversion of int32 to double .
long-to-int int64 a;
int32 result = (int32) a;
Truncation of int64 into int32 .
long-to-float int64 a;
float result = (float) a;
Conversion of int64 to float , using round-to-nearest. This loses precision for some values.
long-to-double int64 a;
double result = (double) a;
Conversion of int64 to double , using round-to-nearest. This loses precision for some values.
float-to-int float a;
int32 result = (int32) a;
Conversion of float to int32 , using round-toward-zero. NaN and -0.0 (negative zero) convert to the integer 0 . Infinities and values with too large a magnitude to be represented get converted to either 0x7fffffff or -0x80000000 depending on sign.
float-to-long float a;
int64 result = (int64) a;
Conversion of float to int64 , using round-toward-zero. The same special case rules as for float-to-int apply here, except that out-of-range values get converted to either 0x7fffffffffffffff or -0x8000000000000000 depending on sign.
float-to-double float a;
double result = (double) a;
Conversion of float to double , preserving the value exactly.
double-to-int double a;
int32 result = (int32) a;
Conversion of double to int32 , using round-toward-zero. The same special case rules as for float-to-int apply here.
double-to-long double a;
int64 result = (int64) a;
Conversion of double to int64 , using round-toward-zero. The same special case rules as for float-to-long apply here.
double-to-float double a;
float result = (float) a;
Conversion of double to float , using round-to-nearest. This loses precision for some values.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
Truncation of int32 to int8 , sign extending the result.
int-to-char int32 a;
int32 result = a & 0xffff;
Truncation of int32 to uint16 , without sign extension.
int-to-short int32 a;
int32 result = (a << 16) >> 16;
Truncation of int32 to int16 , sign extending the result.
add-int int32 a, b;
int32 result = a + b;
Twos-complement addition.
sub-int int32 a, b;
int32 result = a - b;
Twos-complement subtraction.
rsub-int int32 a, b;
int32 result = b - a;
Twos-complement reverse subtraction.
mul-int int32 a, b;
int32 result = a * b;
Twos-complement multiplication.
div-int int32 a, b;
int32 result = a / b;
Twos-complement division, rounded towards zero (that is, truncated to integer). This throws ArithmeticException if b == 0 .
rem-int int32 a, b;
int32 result = a % b;
Twos-complement remainder after division. The sign of the result is the same as that of a , and it is more precisely defined as result == a - (a / b) * b . This throws ArithmeticException if b == 0 .
and-int int32 a, b;
int32 result = a & b;
Bitwise AND.
or-int int32 a, b;
int32 result = a | b;
Bitwise OR.
xor-int int32 a, b;
int32 result = a ^ b;
Bitwise XOR.
shl-int int32 a, b;
int32 result = a << (b & 0x1f);
Bitwise shift left (with masked argument).
shr-int int32 a, b;
int32 result = a >> (b & 0x1f);
Bitwise signed shift right (with masked argument).
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
Bitwise unsigned shift right (with masked argument).
add-long int64 a, b;
int64 result = a + b;
Twos-complement addition.
sub-long int64 a, b;
int64 result = a - b;
Twos-complement subtraction.
mul-long int64 a, b;
int64 result = a * b;
Twos-complement multiplication.
div-long int64 a, b;
int64 result = a / b;
Twos-complement division, rounded towards zero (that is, truncated to integer). This throws ArithmeticException if b == 0 .
rem-long int64 a, b;
int64 result = a % b;
Twos-complement remainder after division. The sign of the result is the same as that of a , and it is more precisely defined as result == a - (a / b) * b . This throws ArithmeticException if b == 0 .
and-long int64 a, b;
int64 result = a & b;
Bitwise AND.
or-long int64 a, b;
int64 result = a | b;
Bitwise OR.
xor-long int64 a, b;
int64 result = a ^ b;
Bitwise XOR.
shl-long int64 a;
int32 b;
int64 result = a << (b & 0x3f);
Bitwise shift left (with masked argument).
shr-long int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitwise signed shift right (with masked argument).
ushr-long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitwise unsigned shift right (with masked argument).
add-float float a, b;
float result = a + b;
Floating point addition.
sub-float float a, b;
float result = a - b;
Floating point subtraction.
mul-float float a, b;
float result = a * b;
Floating point multiplication.
div-float float a, b;
float result = a / b;
Floating point division.
rem-float float a, b;
float result = a % b;
Floating point remainder after division. This function is different than IEEE 754 remainder and is defined as result == a - roundTowardZero(a / b) * b .
add-double double a, b;
double result = a + b;
Floating point addition.
sub-double double a, b;
double result = a - b;
Floating point subtraction.
mul-double double a, b;
double result = a * b;
Floating point multiplication.
div-double double a, b;
double result = a / b;
Floating point division.
rem-double double a, b;
double result = a % b;
Floating point remainder after division. This function is different than IEEE 754 remainder and is defined as result == a - roundTowardZero(a / b) * b .