что такое smali код
Начинаем со Smali. Как реверсить приложения для Android
Содержание статьи
Какое приложение мы будем препарировать? Я выбрал для своих целей VK Admin — программу для управления сообществами «ВКонтакте» со смартфона. В нем не предусмотрена темная тема, поэтому мы с тобой попробуем эту тему добавить.
WARNING
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный изложенным материалом.
Собираем и разбираем
Сначала извлечем все ресурсы приложения, используя утилиту apktool — она распаковывает и запаковывает файлы пакетов APK, которые хранятся в сжатом, бинарном виде, и дизассемблирует программный код, заключенный в них.
Чтобы получить установочный пакет, можно воспользоваться Android Debugging Bridge — системой для отладки программ на устройстве. В *nix-подобных системах ADB ставится стандартно, с помощью пакетного менеджера, а в Windows — идет в составе Android Studio или Android SDK Platform Tools.
В первую очередь установим приложение из Google Play Store на смартфон, подключим его к компьютеру с помощью USB, затем воспользуемся ADB для переноса пакета приложения на компьютер и извлечем его содержимое.
$ adb shell pm path com.vk.admin
package:/data/app/com.vk.admin-Ka5KVtTbnGgxoRqnObb-pQ==/base.apk
$ adb pull /data/app/com.vk.admin-Ka5KVtTbnGgxoRqnObb-pQ==/base.apk com.vk.admin.apk
3881 KB/s (13414132 bytes in 3.374s)
$ apktool d com.vk.admin.apk
I: Using Apktool 2.4.0 on base.apk
I: Loading resource table.
I: Decoding AndroidManifest.xml with resources.
I: Regular manifest package.
I: Decoding file-resources.
I: Decoding values / XMLs.
I: Baksmaling classes.dex.
I: Copying assets and libs.
I: Copying unknown files.
I: Copying original files.
$ apktool b com.vk.admin/
I: Using Apktool 2.4.0
I: Checking whether resources has changed.
I: Checking whether sources has changed.
I: Smaling classes folder into classes.dex.
I: Building apk file.
I: Copying unknown files/dir.
I: Built apk.
Затем необходимо подписать приложение. Это нужно, чтобы и Google Play Store, и устройство не обновляли приложение, если подписи не совпадают. Поэтому не забудь удалить приложение с телефона, прежде чем установить свое, подписанное своим ключом. Для создания подписи в первый раз нужно воспользоваться утилитой keytool (входит в Java Development Kit):
Enter key password for
(RETURN if same as keystore password):
Re-enter new password:
Когда ты уже создал ключ, подпиши приложение.
После этого установи приложение на телефон.
$ adb install com.vk.admin.apk
3881 KB/s (13414132 bytes in 3.374s)
Success
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Учимся считать в hex, или реверс-инженеринг будильника
Введение
Недавно у меня появилась мысль научиться считать в шестнадцатеричной системе счисления. Так как я человек ленивый, такие способы, как выучить таблицу умножения меня не устраивали. Немного поразмыслив, я вспомнил, что каждое утро решаю (иногда несколько раз) несложный пример, чтобы отключить будильник. Помогает слабо, со временем я начал решать почти не просыпаясь. Так почему бы не совместить полезное с полезным?
Осталось выбрать способ реализации. Так как я не имею не малейшего представления о разработке под андроид (да и вообще с Java не сильно знаком), да и писать свое приложение ради такой мелочи — это стрельба из пушки по воробьям, было решено модифицировать уже имеющийся будильник.
Под катом вы найдете описание инструментов, процесса и результата перевода примера в hex. А также объяснение синтаксиса smali кода (язык опкодов для виртуальной машины dalvik). Картинок почти нет, буков много.
Получение читабельного кода
Итак, берем файл нашего приложения (в моем случае это AlarmDroid) и разархивируем его. Есть много способов сделать это, я пользовался Apk Manager, о котором я еще напишу чуть ниже. Далее нужно конвертировать classes.dex в jar. Для этого есть dex2jar. Перетаскиваем файл на dex2jar.bat. Теперь нужно научиться читать получившийся jar файл. Используем для этого программу jd-gui (кстати есть одноименный плагин для Eclipse).
Итак мы получили почти читаемый код, хотя кое-где декомпилятор явно плющит.
Первая кровь
Для начала неплохо было бы сделать генерацию чисел не до 10, а до 15. Изучаем код, и находим метод генерации примера. Поискать его придется, классов в деревьях много. Но так как названия методов сохранились, это не очень сложно.
Находим искомый метод в классе RingerActivity.
Ну вроде все, просто: генерируем 3 числа и 2 знака, и кладем результат в this.x (это нам, кстати, пригодится).
Теперь находим этот же метод в smali-коде (к сожалению в онлайне нету хайлайтеров smali кода, а свой писать лениво, поэтому код будет скринами).
(Код метода продолжается дальше)
Код непонятный, но явно видно что константы задаются один раз в начале. Поэтому меняем 0xa на 0xf и пытаемся увидеть изменения, чтобы знать что мы на верном пути. С помощью Apk Manager собираем, подписываем, перекачиваем на телефон (можно тестировать на эмуляторе, если установлен Android SDK), устанавливаем, ставим будильник на минуту вперед, ждем, смотрим. Эту процедуру придется повторять большое количество раз. Числа на экране увеличились, ошибок не возникает. Отлично! Теперь самое время немного разобраться в непонятном smali коде.
Разбираемся в smali коде
В общем-то все довольно хорошо описано вот тут, я лишь вкратце и по-русски перескажу.
Типы, методы, поля
Lpackage / name / ObjectName ;-> MethodName ( III ) Z
method ( I [ [ IILjava / lang / String ; [ Ljava / lang / Object ; ) Ljava / lang / String ;
Lpackage / name / ObjectName ;-> FieldName : Ljava / lang / String ;
Здесь в общем-то все и так ясно.
Регистры
В smali коде все регистры 32 битные и могут содержать любой тип значений. Для 64 битных значений используются 2 регистра.
Определение количества регистров в методе
Передача параметров
в него, помимо двух интов, передается LMyObject; перед обоими интами, и получается, что в методе 3 параметра. И если вы задали общее количество регистров в методе 5 (или локальное количество 2), то в v2 попадет объект, в v3 — первый инт, в v4 — второй.
Именование регистров
Есть 2 схемы именования регистров: общая v-схема, и p-схема для регистров параметров. В вышеизложенном примере у нас будут 5 общих регистров v0-v4, и 3 регистра параметров p0-p2, причем как было сказано выше p0 и v2 (а также p1 и v3, p2 и v4) обозначают один и тот же регистр.
В общем есть еще некоторые тонкости, но нам для изменения будильника они не важны.
Перевод примера в hex
для всех трех чисел.
Изменение поля ввода
и тут тоже добавляем перевод в верхний регистр. Собираем, смотрим. Ура! Все работает.
Заключение
Скоро сказка сказывается, да не скоро дело делается. Из-за отсутствия дебаггера, тестирование очень сложно, для того чтобы запустить приложение и проверить его работоспособность требуется пара минут, и много надоедающих действий.
Также очень хотелось переделать цифровую раскладку моей любимой клавиатуры Swype для ввода в hex. Но их зашифрованные файлы раскладок стали для меня неодолимым препятствием. =(
Вот финальная версия будильника. К сожалению обновляться после модификации он перестал. Ну да мне и нынешнего функционала хватает.
Спасибо за внимание, буду рад любой критике!
Русские Блоги
Глава 5 Статический анализ программ Android (1) (читать код smali)
Каталог статей
Статический анализ программ Android
Введение в статический анализ
Методы статического анализа программ Android
Читать код smali
файловая структура smali
Объявление класса
Комментарий
аннотация
метод
оператор цикла
Вторая форма состоит в том, чтобы вручную получить итератор, а затем вызвать hasNext () в итераторе в цикле, чтобы проверить, пуст ли он, и, наконец, вызвать его next () в теле цикла для обхода итератора.
Теперь декомпилируйте пример программы Circulate (пример кода:GitHub). Откройте файл MainActivity.smali в каталоге smali / com / droider / circate проекта декомпиляции и найдите метод iterator (). Код выглядит следующим образом:
В приведенном выше коде итератор () List вызывается для получения итератора списка процессов, а затем он входит в цикл итерации из goto_0. В цикле сначала вызывается hasNext () итератора, чтобы проверить, пуст ли итератор. Если итератор пуст, перейдите к cond_0 и вызовите Toas, чтобы вывести всю информацию о процессе; если итератор не пуст, это означает, что содержимое итератора еще не было выполнено, и для получения одного итератора необходимо вызвать next () RunningAppProcessInfo, а затем создайте новый временный StringBuilder, объедините имя процесса и символ новой строки и добавьте его в StringBuilder, созданный перед началом цикла, и, наконец, используйте оператор goto для перехода к началу цикла.
Можно видеть, что этот код очень похож на оператор цикла while, перечисленный ранее. Фактически, первый тип цикла итератора является реализацией цикла второго типа. Хотя их код Java отличается, сгенерированный код дизассемблирования очень похож. аналогичный
Особенности циклов итератора:
Цикл итератора вызывает hasNext () итератора, чтобы проверить, выполняются ли условия цикла.
Цикл итератора вызывает next () итератора для получения единственного объекта.
Цикл итератора использует инструкцию goto для управления потоком кода.
После того, как цикл итератора for-form развернут, это цикл итератора while-form
Далее идет традиционный цикл for. Посмотрите на forCirculate () в файле MainActivity.smali, код:
Особенности кода цикла:
Перед входом в цикл инициализируйте переменную счетчика цикла и измените ее значение в теле цикла.
Оценка условия цикла может быть законным утверждением, состоящим из инструкций условного перехода.
Используйте инструкцию goto для управления потоком кода в цикле
Структура циклов while и do while не сильно отличается. Код этих двух очень похож на код предыдущего цикла итератора, но расположение оценки условия цикла отличается.
оператор переключения ветви
инструкция try / catch
(0x503ac + 5 * 2) = 0x503ae
Русские Блоги
Основы смальского языка
Что такое Смали?
Введение
Основы смальского языка
Следующее содержание относится к структуре и базовому синтаксису некоторых программ на Smali. Эти базовые синтаксисы необходимо использовать при использовании Smali для изменения логики приложения.
Smali файловая структура
основной тип
Введите ключевые слова | Соответствует описанию типа в Java |
---|---|
V | void, может использоваться только для типа возврата |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long (64 bits) |
F | float |
D | double (64 bits) |
объект
Тип объекта, то есть объект ссылочного типа, при обращении к нему начинается с L, за которым следует полное имя пакета, например: java.lang.String Соответствующий синтаксис Smali Ljava/lang/String
массив
Объявление метода и вызов
Шаблон справочного метода Smali, приведенный в официальной вики, выглядит следующим образом:
Lpackage/name/ObjectName;->MethodName(III)Z
Часть 1 Lpackage/name/ObjectName; Используется для объявления определенных типов для JVM, чтобы найти
Поскольку список параметров метода не разделен запятой, его можно разделить только слева направо в соответствии с определением типа. Это необходимо соблюдать осторожно.
Если вам нужно вызвать конструктор, MethodName:
Зарегистрировать декларацию и использовать
В Smali, если вам нужно хранить переменные, вы должны сначала объявить достаточное количество регистров, один регистр может хранить 32-битные типы длины, такие как Int, и два регистра могут хранить 64-битные типы данных, такие как Long или Double
В сочетании с обычно используемыми инструкциями Dalvik, вы можете достичь некоторых необходимых функций
Итак, как определить количество регистров, которые будут использоваться?
Из-за нестатического метода вам нужно занять регистр для сохранения этого указателя, тогда минимальное количество регистров этого типа метода равно 1, если вам нужно обработать входящие параметры, вам нужно добавить еще раз, в это время вы должны рассмотреть Double и Float Этот тип параметра должен занимать два регистра, например:
Если метод Java объявлен следующим образом:
myMethod(int p1, float p2, boolean p3)
Тогда соответствующий сомали это:
method LMyObject;->myMethod(IJZ)V
В настоящее время соответствующая ситуация с регистром выглядит следующим образом:
Зарегистрировать имя | Соответствующая ссылка |
---|---|
p0 | this |
p1 | параметр p1 типа int |
p2, p3 | параметр типа p2 с плавающей точкой |
p4 | логический параметр p3 |
Тогда минимальное количество необходимых регистров: 5
Если метод содержит определения констант, переменных и т. Д., Вам необходимо увеличить количество регистров в соответствии с ситуацией. Пока число соответствует требованиям, убедитесь, что значение, которое необходимо получить, не вымывается при последующем присвоении. После сохранения регистр можно переназначить) или занять реестр на долгое время
Набор инструкций Dalvik
Если вам нужно написать программу с использованием Smali, вам также необходимо освоить часто используемые инструкции виртуальной машины Dalvik, которые называются набором команд Dalvik. Эти инструкции в некоторой степени похожи на инструкции по сборке x86, но есть больше инструкций, и они очень просты и удобны в использовании. Для более подробного ознакомления вы можете обратиться к официальным документам Android, связанным с Dalvik:https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions
Вот также некоторые часто используемые инструкции, в сочетании с Smali для объяснения:
Используется для возврата значения, соответствующего оператору возврата в Java
Используется для объявления констант, таких как строковые константы (только объявления, String a = «abc» Такие заявления включают декларацию и уступку)
инструкция | объяснение |
---|---|
if-eq v1,v2 | Определить, равны ли значения в двух регистрах |
if-ne v1,v2 | Определите, не равны ли значения в двух регистрах |
if-lt v1,v2 | Определите, меньше ли значение в регистре v1, чем значение в регистре v2 (lt == меньше чем) |
if-ge v1,v2 | Определите, больше или равно ли значение в регистре v1 значению в регистре v2 (ge == больше или равно) |
if-gt v1,v2 | Определите, больше ли значение в регистре v1, чем значение в регистре v2 (gt == great than) |
if-le v1,v2 | Определите, является ли значение в регистре v1 меньше или равно значению в регистре v2 (le == меньше или равно) |
Следует отметить, что если операторы, написанные на Java, часто в соответствующих Smali, станут противоположной логикой суждения, как показано ниже:
Соблюдайте внимательно:
Атрибутивные операции делятся на: получить и положить
Целевой тип делится на: массив (массив), экземпляр (экземпляр) и статический (статический) три, соответствующий сокращенный префикс a, i, s
Типы длины делятся на: по умолчанию (ничего не писать), широкий (широкий, 64-битный) 、 объект 、 boolean 、 byte 、 char 、 short (Последние несколько не будут объяснены, в соответствии с Java)
Формат инструкции: [Имя команды] [регистр источника], [регистр объекта, в котором находится поле назначения], [указатель поля] Пример кода следующий: операция заключается в присвоении значения 100 переменной члена класса mIntA типа int:
Инструкции для поля экземпляра перечислены ниже, где я могу быть заменен на a или s, которые используются для манипулирования полями массива или статическими полями, соответственно
инструкция | объяснение |
---|---|
iget | Значение, используемое для манипулирования типом значения int |
iget-wide | Значение, используемое для работы широкого поля |
iget-object | Значение, используемое для управления ссылками на объект |
iget-boolean | Значение, используемое для работы с логическим типом |
iget-byte | Значение, используемое для манипулирования типом байта |
iget-char | Значение, используемое для манипулирования типом символа |
iget-short | Значение, используемое для работы короткого типа |
iput | Назначение, используемое для манипулирования типами значений, такими как int |
iput-wide | Назначение, используется для работы широкого поля |
iput-object | Назначение, используемое для управления ссылками на объекты |
iput-boolean | Назначение, используемое для управления булевыми типами |
iput-byte | Назначение, используемое для манипулирования типами байтов |
iput-char | Назначение, используемое для управления типами символов |
iput-short | Назначение, используется для работы короткого типа |
Следующий Java-код предназначен для самых простых операций присваивания и значения переменных класса.
Соответствующий код Smali выглядит следующим образом:
В соответствии со сравнением кода Java и Smali, стоит отметить, что метод получения переменных класса в Smali ближе к вызовам функций, но нет никаких параметров для вызовов функций
В дополнение к базовым инструкциям Dalvik, представленным выше, Dalvik также поддерживает два типа наборов команд: преобразование типов значений (например, int в float, double в float и т. Д.) И базовые операции (математические операции, логические операции, самоинкремент). Перечислите некоторые общие инструкции, другие могут ссылаться на официальные документы Google, упомянутые выше
Что может сделать Смали?
Хотя мы понимаем основной синтаксис Smali, мы, как правило, не пишем напрямую Smali для разработки функций, что является слишком дорогостоящим, и цель понимания Smali состоит в том, чтобы выполнить реверс-инжиниринг Android, такой как: анализ принципов APP, обнаружение уязвимостей, Конечно, вы также можете внести некоторые незначительные изменения в некоторые приложения (лучше не делать вещи, которые наносят ущерб закону, нарушают закон и дисциплину, и вредят другим)
Шпаргалка по Smali на русском
Приветствую, любители реверс-инжинирить Android. Перед вами шпаргалка по Smali — аналогу ассемблера для Android-приложений.
Изначальный текст на русском взят отсюда. Там текст появился из машинного перевода официальной документации.
В итоге, оформил сухой текст + поправил небольшие опечатки и корявости перевода. По поводу замечаний и предложений можете писать либо мне в ЛС, либо оформлять PR на Gist.
Общая информация
Виды(Types)
Байт-код Dalvik имеет два основных класса типов: примитивные типы и ссылочные типы. Типы ссылок — это объекты и массивы, все остальное является примитивным.
Примитивы представлены одной буквой:
Объекты принимают форму Lpackage/name/ObjectName; — где ведущий L указывает, что это тип объекта, package/name/ — это пакет, в котором находится объект, ObjectName — это имя объекта и ; обозначает конец имени объекта.
Это эквивалентно имени package.name.ObjectName в java. Или, для более конкретного примера, Ljava/lang/String; эквивалентно java.lang.String
Вы также можете иметь массивы объектов, [Ljava/lang/String; будет массив строк.
Методы(Methods)
Методы всегда указываются в очень подробной форме, которая включает тип, содержащий метод, имя метода, типы параметров и тип возвращаемого значения. Вся эта информация необходима, чтобы виртуальная машина могла находить правильный метод и иметь возможность выполнять статический анализ на байт-коде
Они принимают форму Lpackage/name/ObjectName;->MethodName(III)Z
В этом примере вы должны распознать Lpackage/name/ObjectName; как тип. MethodName — это имя метода. (III)Z является сигнатурой метода. III — параметры (в данном случае 3 целых числа), а Z — тип возврата (bool).
Параметры метода перечислены один за другим, без разделителей между ними.
Вот более сложный пример:
В Java, это было бы
Поля(Fields)
Поля также всегда указывается в многословной форме, которая включает тип, содержащее поле, имя поля и тип поля. Опять же, это позволяет виртуальной машине находить правильное поле, а также выполнять статический анализ на байт-коде.
Они принимают форму Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
Это должно быть довольно очевидно — это пакет и имя объекта, имя поля и тип поля соответственно
Регистры (Register)
Вступление
В байт-коделе dalvik регистры всегда 32 битные и могут содержать любой тип значения. 2 регистра используются для хранения 64-битных типов (длинного — Long и числа с плавающей точкой — Double).
Указание количества регистров в методе
Как параметры метода передаются в метод:
Первым параметром для нестатических методов ( non-static methods ) всегда является объект, на который вызывается метод ( this объект)
Для статических методов ( static methods ) это одно и то же, за исключением того, что неявный этот аргумент.
Регистрация имен (Register names)
Существует две схемы именования для регистров — обычная схема именования v# и схема именования p# для регистров параметров. Первый регистр в схеме именования p# является первым регистром параметров в методе.
Итак, вернемся к предыдущему примеру метода с 3-мя аргументами и 5-ю полными регистрами. В следующей таблице показано обычное имя v# для каждого регистра, за которым следует имя p# для регистров параметров ( parameter registers )
v# | p# | |
---|---|---|
v0 | Первый локальный регистр | |
v1 | Второй локальный регистр | |
v2 | p0 | Первый регистр параметров |
v3 | p1 | Второй регистр параметров |
v4 | p2 | Третий регистр параметров |
Вы можете ссылаться на регистры параметров по имени — это не имеет никакого значения.
Введения регистров параметров ( parameter registers )
Но если схема именования p# использовалась для ссылки на регистры параметров во всем методе, вы можете легко изменить количество регистров в методе, не беспокоясь о перонумеровании любых существующих регистров.
Long/Double значения
Кроме того, когда вы вызываете метод позже, вам нужно указать оба регистра для любых аргументов с двойным расширением в списке регистров для инструкции типа invoke.
Array (массивы)
array-length vA, vB
Сохраняет длину (количество записей) указанного массива vB в vA
fill-array-data vA+, :target
Пример таблицы данных:
new-array vA+, vB, Lclass;->type
Создает новый массив указанного типа и размера. Тип должен быть типом массива.
filled-new-array < vA [ vB, v. vX ]>, Lclass;->type
Array Accessors (приемники массивов)
Сохраняет целое ( integer ) значение от vA в массиве, на который ссылается vB на индекс vC
Например: aget-objec (Получает объект( object ))
Сравнения
cmp-long vA, vB+, vC+
Сравнивает длинные (long) значения в исходных регистрах, сохраняя 0
cmpg-double vA, vB+, vC+
Сравнивает числа с плавающей точкой (double) значения в исходных регистрах, сохраняя 0
cmpg-float vA, vB, vC
Сравнивает значения с плавающей(float) запятой в исходных регистрах, сохраняя 0;
cmpl-double vA, vB+, vC+
Сравнивает double значения в исходных регистрах, сохраняя 0;
cmpl-float vA, vB, vC — выполняет указанное сравнение с плавающей(float) запятой, сохраняя 0;
Константы
const vAA, #+BBBBBBBB
const/16 vAA, #+BBBB
Заносит #+BBBB в регистр vAA
const/4 vA, #+B
const/high16 vAA, #+BBBB
const-class vAA, Lclass
const-string vAA, «BBBB»
Переместит ссылку на строку, указанную в регистре назначения vAA
const-string/jumbo vAA, «BBBBBBBB»
Переместит ссылку на строку, указанную в регистре назначения vAA
jumbo — обозначает, что значение будет «большим»
Еще примеры:
const-wide/16 vA+, #+BBBB
const-wide/high16 vA+, #+BBBB
const-wide vA+, #+BBBBBBBBBBBBBBBB
Go To
goto — Безусловный переход к :target.
Только замена не может производиться на оборот: goto не может заменить goto/16, а он в свою очередь не может заменить goto/32.
Условия
if — Если выполняется условие, происходит переход по метке
Примеры:
Invoke
Вызывает метод интерфейса ( interface method ) (то есть объект, чей конкретный класс неизвестен, используя метод, который ссылается на интерфейс):
Вызывает статический метод ( static method ) (который всегда считается прямым методом):
Вызывает виртуальный метод ( virtual method ) непосредственного родительского класса:
Вызывает виртуальный метод ( virtual method ) (метод, который не является статическим или окончательным, и не является конструктором):
Примечание:
Если метод возвращает значение ( R не является « V » для Void), он должен быть зафиксирован в следующей строке одним из операторов move-result или он будет потерян.
И так можно делать с любым выше перечисленным invoke:
Прочее
check-cast vAA, Lclass
instance-of vA, vB, Lclass
new-instance vAA, Lclass
Пустая команда/Нет операции
throw vAA
Прим: A: x bits. B: x bits не является частью кода. Добавил только для обозначения бит в регистрах
move vA, vB
Перемещает содержимого одного регистра не-объекта (non-object) к другому.
move/16 vAAAA, vBBBB
A: 16 bits. B: 16 bits
move/from16 vAA, vBBBB
A: 8 bits. B: 16 bits
move-exception vAA
move-object vA, vB
Перемещает содержимое одного объекта, несущего регистра в другой.
move-object/16 vAAAA, vBBBB
A: 16 bits. B: 16 bits
move-object/from16 vAA, vBBBB
A: 8 bits. B: 16 bits
move-result vAA
move-result-object vAA
Остальное кратко:
Операции
Оператор ADD
Cкладывает значения по обе стороны от оператора
add-double vA+, vB+, vC+
Вычисляет vB+ + vC+ и сохраняет результат в vA+
add-double/2addr vA+, vB+
Вычисляет vA + vB и сохраните результат в vA+
add-float vA, vB, vC
Вычисляет vB + vC и сохраняет результат в vA
add-float/2addr vA, vB
Вычисляет vA + vB и сохраняет результат в vA
add-int vA, vB, vC
Вычисляет vB + vC и сохраняет результат в vA
add-int/lit8 vA, vB, 0xC
Вычисляет vB + 0xC и сохраняет результат в vA
add-int/lit16 vA, vB, 0xC
Вычисляет vB + 0xC и сохраняет результат в vA
add-int/2addr vA, vB
Вычисляет vA + vB и сохраняет результат в vA
Оператор AND
Бинарный оператор копирует бит в результат, если он существует в обоих операндах.
Оператор DIV
Делит левый операнд на правый операнд
Оператор MUL
Умножает значения по обе стороны от оператора
Оператор OR
Копирует бит, если он существует в любом из операндов.
Оператор REM
Делит левый операнд на правый операнд и возвращает остаток
Оператор SHL
Значение левых операндов перемещается влево на количество бит, заданных правым операндом.
Оператор SHR
Значение правых операндов перемещается вправо на количество бит, заданных левых операндом.
Оператор SUB
Вычитает из правого операнда левый операнд
Оператор USHR
Оператор XOR
копирует бит, если он установлен в одном операнде, но не в обоих.
Return
Оператор return используется для выполнения явного возврата из метода. То есть он снова передает управление объекту, который вызвал данный метод. Оператор return предписывает интерпретатору остановить выполнение текущего метода. Если метод возвращает значение, оператор return сопровождается некоторым выражением. Значение этого выражения становится возвращаемым значением метода.
return vAA
Возврат из метода возвращаемого значения non-object со значением vAA.
return-object vAA
Возврат из метода object-returning с помощью object-reference в vAA.
return-void
Возврат из метода void без значения.
return-wide vA+
Switch-и
packed-switch vAA, :target
Легенда:
sparse-switch vAA, :target
Реализует оператор switch, где константы case не являются последовательными. В инструкции используется таблица поиска с константами case и смещениями для каждой константы случая. Если в таблице нет соответствия, выполнение продолжается в следующей команде (случай по умолчанию).