Kod bajtowy Dalvik

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Ogólny projekt

  • Model maszyny i konwencje wywoływania mają w przybliżeniu naśladować typowe rzeczywiste architektury i konwencje wywoływania w stylu C:
    • Maszyna jest oparta na rejestrach, a rozmiary ramek są ustalane podczas tworzenia. Każda ramka składa się z określonej liczby rejestrów (określonych przez metodę) oraz wszelkich danych pomocniczych potrzebnych do wykonania metody, takich jak (ale nie tylko) licznik programu i odniesienie do pliku .dex zawierającego metodę .
    • Gdy są używane do wartości bitowych (takich jak liczby całkowite i liczby zmiennoprzecinkowe), rejestry są uważane za 32-bitowe. Sąsiednie pary rejestrów są używane dla wartości 64-bitowych. Nie ma wymogu wyrównania par rejestrów.
    • W przypadku odniesień do obiektów rejestry są uważane za wystarczająco szerokie, aby pomieścić dokładnie jedno takie odniesienie.
    • Pod względem reprezentacji bitowej (Object) null == (int) 0 .
    • N argumentów metody ląduje w ostatnich N rejestrach ramki wywołania metody, w kolejności. Szerokie argumenty zajmują dwa rejestry. Metody instancji są przekazywane jako referencja this jako ich pierwszy argument.
  • Jednostka pamięci w strumieniu instrukcji jest 16-bitową liczbą bez znaku. Niektóre bity w niektórych instrukcjach są ignorowane / musi być zero.
  • Instrukcje nie są bezpodstawnie ograniczone do określonego typu. Na przykład instrukcje, które przenoszą 32-bitowe wartości rejestrów bez interpretacji, nie muszą określać, czy przenoszą wartości całkowite czy zmiennoprzecinkowe.
  • Istnieją oddzielnie wyliczane i indeksowane pule stałych dla odwołań do ciągów, typów, pól i metod.
  • Dosłowne dane bitowe są reprezentowane w linii w strumieniu instrukcji.
  • Ponieważ w praktyce rzadko zdarza się, aby metoda wymagała więcej niż 16 rejestrów, a ponieważ potrzeba więcej niż ośmiu rejestrów jest dość powszechna, wiele instrukcji ogranicza się do adresowania tylko pierwszych 16 rejestrów. Gdy jest to rozsądnie możliwe, instrukcje pozwalają na odniesienia do pierwszych 256 rejestrów. Ponadto niektóre instrukcje mają warianty, które pozwalają na znacznie większą liczbę rejestrów, w tym parę instrukcji move typu catch-all, które mogą adresować rejestry z zakresu v0v65535 . W przypadkach, gdy wariant instrukcji nie jest dostępny do zaadresowania żądanego rejestru, oczekuje się, że zawartość rejestru zostanie przeniesiona z rejestru pierwotnego do rejestru niskiego (przed operacją) i/lub przeniesiona z rejestru niskiego wyniku do rejestru wysokiego zarejestrować (po operacji).
  • Istnieje kilka „pseudoinstrukcji” używanych do przechowywania ładunków danych o zmiennej długości, do których odwołują się zwykłe instrukcje (na przykład fill-array-data ). Takie instrukcje nigdy nie mogą być napotkane podczas normalnego przebiegu wykonywania. Ponadto instrukcje muszą znajdować się na przesunięciach kodu bajtowego o numerach parzystych (tj. wyrównane do 4 bajtów). Aby spełnić ten wymóg, narzędzia do generowania dex muszą emitować dodatkową instrukcję nop jako odstępnik, jeśli taka instrukcja byłaby w innym przypadku niewyrównana. Na koniec, choć nie jest to wymagane, oczekuje się, że większość narzędzi zdecyduje się emitować te instrukcje na końcach metod, ponieważ w przeciwnym razie prawdopodobnie potrzebne byłyby dodatkowe instrukcje do rozgałęzienia wokół nich.
  • Po zainstalowaniu w działającym systemie niektóre instrukcje mogą zostać zmienione, zmieniając ich format, jako optymalizacja statycznego łączenia w czasie instalacji. Ma to na celu szybsze wykonanie, gdy znane jest połączenie. Sugerowane warianty można znaleźć w powiązanym dokumencie dotyczącym formatów instrukcji . Słowo „sugerowane” jest używane rozmyślnie; ich wdrożenie nie jest obowiązkowe.
  • Ludzka składnia i mnemotechnika:
    • Porządkowanie argumentów według metody Dest-the-source.
    • Niektóre kody operacyjne mają jednoznaczny sufiks nazwy, aby wskazać typ (y), na którym działają:
      • Ogólne 32-bitowe kody operacji są nieoznaczone.
      • Ogólne 64-bitowe kody operacji mają przyrostek -wide .
      • Kody operacji specyficzne dla typu mają sufiks z ich typem (lub prostym skrótem), jednym z: -boolean -byte -char -short -int -long -float -double -object -string -class -void
    • Niektóre kody operacyjne mają sufiks ujednoznaczniający, aby odróżnić identyczne operacje, które mają różne układy instrukcji lub opcje. Przyrostki te są oddzielone od głównych nazw za pomocą ukośnika (" / ") i istnieją głównie po to, aby w kodzie istniało mapowanie jeden do jednego ze stałymi statycznymi, które generuje i interpretuje pliki wykonywalne (to znaczy, aby zmniejszyć niejednoznaczność dla ludzi).
    • W opisach tutaj szerokość wartości (wskazująca np. zakres stałej lub liczbę ewentualnie adresowanych rejestrów) jest podkreślona przez użycie znaku na cztery bity szerokości.
    • Np. w instrukcji " move-wide/from16 vAA, vBBBB ":
      • " move " to bazowy kod operacji, wskazujący podstawową operację (przenieś wartość rejestru).
      • wide ” to przyrostek nazwy wskazujący, że operuje na danych szerokich (64-bitowych).
      • from16 ” jest przyrostkiem kodu operacji, wskazującym na wariant, który ma 16-bitowe odniesienie do rejestru jako źródło.
      • " vAA " jest rejestrem docelowym (implikowanym przez operację; znowu zasada jest taka, że ​​argumenty docelowe zawsze są na pierwszym miejscu), który musi znajdować się w zakresie v0v255 .
      • " vBBBB " to rejestr źródłowy, który musi znajdować się w zakresie v0v65535 .
  • Zobacz dokument o formatach instrukcji, aby uzyskać więcej szczegółów na temat różnych formatów instrukcji (wymienionych w "Op & Format"), a także szczegółów na temat składni kodu operacji.
  • Zobacz dokument w formacie pliku .dex , aby uzyskać więcej informacji o tym, gdzie kod bajtowy pasuje do większego obrazu.

Podsumowanie zestawu kodów bajtowych

Operacje i formaty Mnemonik / składnia Argumenty Opis
00 10x nop Cykle odpadów.

Uwaga: Pseudo-instrukcje zawierające dane są oznaczone tym kodem operacji, w którym to przypadku bajt wyższego rzędu jednostki kodu operacji wskazuje na charakter danych. Zobacz " Format Packed-switch- packed-switch-payload ", "Format sparse-switch-payload " i "Format fill-array-data-payload " poniżej.

01 12x przesuń vA, vB A: rejestr docelowy (4 bity)
B: rejestr źródłowy (4 bity)
Przenieś zawartość jednego rejestru nieobiektowego do drugiego.
02 22x przenieś/z16 vAA, vBBBB A: rejestr docelowy (8 bitów)
B: rejestr źródłowy (16 bitów)
Przenieś zawartość jednego rejestru nieobiektowego do drugiego.
03 32x ruch/16 vAAAA, vBBBB A: rejestr docelowy (16 bitów)
B: rejestr źródłowy (16 bitów)
Przenieś zawartość jednego rejestru nieobiektowego do drugiego.
04 12x vA, vB A: para rejestrów docelowych (4 bity)
B: para rejestrów źródłowych (4 bity)
Przenieś zawartość jednej pary rejestrów do drugiej.

Uwaga: Dozwolone jest przejście z v N do v N-1 lub v N+1 , więc implementacje muszą zapewnić odczytanie obu połówek pary rejestrów przed zapisaniem czegokolwiek.

05 22x przenieś w całej/od 16 vAA, vBBBB A: para rejestrów docelowych (8 bitów)
B: para rejestrów źródłowych (16 bitów)
Przenieś zawartość jednej pary rejestrów do drugiej.

Uwaga: uwagi dotyczące implementacji są takie same jak w move-wide powyżej.

06 32x move-wide/16 vAAAA, vBBBB A: para rejestrów docelowych (16 bitów)
B: para rejestrów źródłowych (16 bitów)
Przenieś zawartość jednej pary rejestrów do drugiej.

Uwaga: uwagi dotyczące implementacji są takie same jak w move-wide powyżej.

07 12x ruch obiektu vA, vB A: rejestr docelowy (4 bity)
B: rejestr źródłowy (4 bity)
Przenieś zawartość jednego rejestru zawierającego obiekt do drugiego.
08 22x przenieś obiekt/z 16 vAA, vBBBB A: rejestr docelowy (8 bitów)
B: rejestr źródłowy (16 bitów)
Przenieś zawartość jednego rejestru zawierającego obiekt do drugiego.
09 32x przenieś obiekt/16 vAAAA, vBBBB A: rejestr docelowy (16 bitów)
B: rejestr źródłowy (16 bitów)
Przenieś zawartość jednego rejestru zawierającego obiekt do drugiego.
0a 11x ruch-wynik vAA A: rejestr docelowy (8 bitów) Przenieś invoke- kind wynik ostatniego wywołania do wskazanego rejestru. Musi to być zrobione jako instrukcja natychmiast po wywołaniu, którego wynik (pojedynczy, invoke- kind ) nie ma być ignorowany; gdziekolwiek indziej jest nieważne.
0b 11x vAA dla całego wyniku ruchu A: para rejestrów docelowych (8 bitów) Przenieś wynik podwójnego słowa ostatniego invoke- kind do wskazanej pary rejestrów. Musi to być zrobione jako instrukcja natychmiast po wywołaniu, którego ( invoke- kind ) wynik nie ma być ignorowany; gdziekolwiek indziej jest nieważne.
0c 11x ruch-wynik-obiekt vAA A: rejestr docelowy (8 bitów) Przenieś wynik obiektu ostatniego invoke- kind do wskazanego rejestru. Musi to być zrobione jako instrukcja natychmiast po invoke- kind lub filled-new-array której wynik (obiekt) nie ma być ignorowany; gdziekolwiek indziej jest nieważne.
0d 11x ruch-wyjątek vAA A: rejestr docelowy (8 bitów) Zapisz właśnie wychwycony wyjątek w podanym rejestrze. Musi to być pierwsza instrukcja obsługi wyjątków, której przechwycony wyjątek nie ma być ignorowany, a instrukcja ta musi zawsze występować tylko jako pierwsza instrukcja obsługi wyjątków; gdziekolwiek indziej jest nieważne.
0e 10x zwrot-unieważnij Powrót z metody void .
0f 11x powrót vAA A: rejestr wartości zwracanych (8 bitów) Zwróć z metody zwracania wartości niebędącej obiektem o pojedynczej szerokości (32-bity).
10 11x vAA dla całego powrotu A: zwracana para rejestrów (8 bitów) Zwróć z metody zwracania wartości o podwójnej szerokości (64-bitowej).
11 11x zwracany obiekt vAA A: rejestr wartości zwracanych (8 bitów) Zwrot z metody zwracania obiektu.
12 11n const/4 vA, #+B A: rejestr docelowy (4 bity)
B: podpisany (4 bity)
Przenieś podaną wartość literału (rozszerzenie znaku do 32 bitów) do określonego rejestru.
13 21s const/16 vAA, #+BBBB A: rejestr docelowy (8 bitów)
B: podpisany (16 bitów)
Przenieś podaną wartość literału (rozszerzenie znaku do 32 bitów) do określonego rejestru.
14 31i const vAA, #+BBBBBBBB A: rejestr docelowy (8 bitów)
B: dowolna 32-bitowa stała
Przenieś podaną wartość literału do określonego rejestru.
15 21h const/high16 vAA, #+BBBB0000 A: rejestr docelowy (8 bitów)
B: podpisany (16 bitów)
Przenieś podaną wartość literału (prawo-zero-rozszerzenie do 32 bitów) do określonego rejestru.
16 21s const-wide/16 vAA, #+BBBB A: rejestr docelowy (8 bitów)
B: podpisany (16 bitów)
Przenieś podaną wartość literału (rozszerzenie znaku do 64 bitów) do określonej pary rejestrów.
17 31 stały szeroki/32 vAA, #+BBBBBBBB A: rejestr docelowy (8 bitów)
B: podpisany (32 bity)
Przenieś podaną wartość literału (rozszerzenie znaku do 64 bitów) do określonej pary rejestrów.
18 51 const-wide vAA, #+BBBBBBBBBBBBBBBBBB A: rejestr docelowy (8 bitów)
B: dowolna stała o podwójnej szerokości (64-bitowa)
Przenieś podaną wartość literału do określonej pary rejestrów.
19 21h stała szeroka/wysoka16 vAA, #+BBBB000000000000 A: rejestr docelowy (8 bitów)
B: podpisany (16 bitów)
Przenieś podaną wartość literału (prawo-zero-rozszerzona do 64 bitów) do określonej pary rejestrów.
1a 21c const-string vAA, string@BBBB A: rejestr docelowy (8 bitów)
B: indeks ciągu
Przenieś odwołanie do ciągu określonego przez dany indeks do określonego rejestru.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: rejestr docelowy (8 bitów)
B: indeks ciągu
Przenieś odwołanie do ciągu określonego przez dany indeks do określonego rejestru.
1c 21c klasa stała vAA, typ@BBBB A: rejestr docelowy (8 bitów)
B: indeks typu
Przenieś odwołanie do klasy określonej przez dany indeks do określonego rejestru. W przypadku, gdy wskazany typ jest prymitywny, przechowa się odwołanie do zdegenerowanej klasy typu pierwotnego.
1d 11x monitor-wprowadź vAA A: rejestr odniesienia (8 bitów) Zdobądź monitor dla wskazanego obiektu.
1e 11x wyjście monitora vAA A: rejestr odniesienia (8 bitów) Zwolnij monitor dla wskazanego obiektu.

Uwaga: Jeśli ta instrukcja musi zgłosić wyjątek, musi to zrobić tak, jakby komputer przeszedł już po instrukcji. Przydatne może być myślenie o tym jako o pomyślnym wykonaniu instrukcji (w pewnym sensie) i wyrzuceniu wyjątku po instrukcji, ale zanim kolejna ma szansę na wykonanie. Ta definicja umożliwia metodzie użycie bloku czyszczenia monitora catch-all (np. w finally ) jako czyszczenia monitora dla samego bloku, jako sposobu obsługi arbitralnych wyjątków, które mogą zostać wyrzucone z powodu historycznej implementacji Thread.stop() , jednocześnie utrzymując odpowiednią higienę monitora.

1f 21c check-cast vAA, type@BBBB A: rejestr odniesienia (8 bitów)
B: indeks typu (16 bitów)
ClassCastException , jeśli odwołanie w danym rejestrze nie może być rzutowane na wskazany typ.

Uwaga: Ponieważ A musi zawsze być odwołaniem (a nie wartością pierwotną), to z konieczności zakończy się niepowodzeniem w czasie wykonywania (to znaczy zgłosi wyjątek), jeśli B odwołuje się do typu pierwotnego.

20 22c wystąpienie vA, vB, type@CCCC A: rejestr docelowy (4 bity)
B: rejestr odniesienia (4 bity)
C: indeks typu (16 bitów)
Zapisz w danym rejestrze docelowym 1 , jeśli wskazane odwołanie jest instancją danego typu, lub 0 , jeśli nie.

Uwaga: Ponieważ B musi zawsze być referencją (a nie wartością pierwotną), zawsze spowoduje to zapisanie 0 , jeśli C odnosi się do typu pierwotnego.

21 12x długość tablicy vA, vB A: rejestr docelowy (4 bity)
B: rejestr odniesienia tablicy (4 bity)
Przechowuj w danym miejscu docelowym zarejestruj długość wskazanej tablicy, we wpisach
22 21c vAA nowej instancji, typ@BBBB A: rejestr docelowy (8 bitów)
B: indeks typu
Skonstruuj nową instancję wskazanego typu, przechowując odwołanie do niej w miejscu docelowym. Typ musi odwoływać się do klasy bez tablicy.
23 22c nowa tablica vA, vB, typ@CCCC A: rejestr docelowy (4 bity)
B: rejestr rozmiarów
C: indeks typu
Skonstruuj nową tablicę wskazanego typu i rozmiaru. Typ musi być typem tablicowym.
24 35c wypełniona nowa tablica {vC, vD, vE, vF, vG}, type@BBBB A: rozmiar tablicy i liczba słów w argumencie (4 bity)
B: indeks typu (16 bitów)
C..G: rejestry argumentów (każdy 4 bity)
Skonstruuj tablicę o podanym typie i rozmiarze, wypełniając ją dostarczoną zawartością. Typ musi być typem tablicowym. Zawartość tablicy musi być jednowyrazowa (to znaczy nie może zawierać tablic long ani double , ale typy odwołań są dopuszczalne). Skonstruowana instancja jest przechowywana jako "wynik" w taki sam sposób, w jaki instrukcje wywoływania metody przechowują swoje wyniki, więc skonstruowana instancja musi zostać przeniesiona do rejestru z następującą bezpośrednio po niej instrukcją move-result-object (jeśli ma być użyta ).
25 3r wypełniona-nowa-tablica/zakres {vCCCC .. vNNNN}, typ@BBBB A: rozmiar tablicy i liczba słów argumentów (8 bitów)
B: indeks typu (16 bitów)
C: rejestr pierwszego argumentu (16 bitów)
N = A + C - 1
Skonstruuj tablicę o podanym typie i rozmiarze, wypełniając ją dostarczoną zawartością. Wyjaśnienia i ograniczenia są takie same, jak w przypadku metody filled-new-array opisanej powyżej.
26 31t fill-array-data vAA, +BBBBBBBB (z dodatkowymi danymi określonymi poniżej w „ fill-array-data-payload Format”) A: odwołanie do tablicy (8 bitów)
B: podpisane przesunięcie „gałęzi” do pseudoinstrukcji danych tabeli (32 bity)
Wypełnij podaną tablicę wskazanymi danymi. Odwołanie musi odnosić się do tablicy prymitywów, a tabela danych musi odpowiadać jej pod względem typu i nie może zawierać więcej elementów, niż zmieści się w tablicy. Oznacza to, że tablica może być większa niż tablica, a jeśli tak, ustawiane są tylko początkowe elementy tablicy, pozostawiając resztę samą.
27 11x rzut vAA A: rejestr z wyjątkami (8 bitów)
Wyrzuć wskazany wyjątek.
28 10t przejdź do +AA A: podpisane przesunięcie gałęzi (8 bitów) Bezwarunkowo przeskocz do wskazanej instrukcji.

Uwaga: Przesunięcie rozgałęzienia nie może wynosić 0 . (Pętla spinowa może być legalnie skonstruowana albo za pomocą goto/32 , albo przez nop jako celu przed gałęzią.)

29 20t goto/16 +AAAA A: podpisane przesunięcie gałęzi (16 bitów)
Bezwarunkowo przeskocz do wskazanej instrukcji.

Uwaga: Przesunięcie rozgałęzienia nie może wynosić 0 . (Pętla spinowa może być legalnie skonstruowana albo za pomocą goto/32 , albo przez nop jako celu przed gałęzią.)

2a 30t goto/32 +AAAAAAAA A: podpisane przesunięcie gałęzi (32 bity)
Bezwarunkowo przeskocz do wskazanej instrukcji.
2b 31t Packed-switch vAA, +BBBBBBBB (z dodatkowymi danymi określonymi poniżej w "Packed packed-switch-payload Format") A: zarejestruj się, aby przetestować!
B: podpisane przesunięcie „gałęzi” do pseudoinstrukcji danych tabeli (32 bity)
Skok do nowej instrukcji na podstawie wartości w danym rejestrze, używając tabeli przesunięć odpowiadającej każdej wartości w określonym zakresie całkowitym, lub przejdź do następnej instrukcji, jeśli nie ma dopasowania.
2c 31t sparse-switch vAA, +BBBBBBBB (z dodatkowymi danymi określonymi poniżej w " sparse-switch-payload Format") A: zarejestruj się, aby przetestować!
B: podpisane przesunięcie „gałęzi” do pseudoinstrukcji danych tabeli (32 bity)
Przejdź do nowej instrukcji na podstawie wartości w danym rejestrze, używając uporządkowanej tabeli par wartość-przesunięcie, lub przejdź do następnej instrukcji, jeśli nie ma dopasowania.
2d..31 23x rodzaj cmp vAA, vBB, vCC
2d: cmpl-float (odchylenie lt)
2e: cmpg-float (odchylenie gt)
2f: cmpl-double (odchylenie lt)
30: cmpg-double (odchylenie gt)
31: cmp-długość
A: rejestr docelowy (8 bitów)
B: pierwszy rejestr źródłowy lub para
C: drugi rejestr źródłowy lub para
Wykonaj wskazaną liczbę zmiennoprzecinkową lub long porównanie, ustawiając a na 0 , jeśli b == c , 1 jeśli b > c , lub -1 jeśli b < c . „Odchylenie” wymienione dla operacji zmiennoprzecinkowych wskazuje, jak traktowane są porównania NaN : instrukcje „gt bias” zwracają 1 dla porównań NaN , a instrukcje „lt bias” zwracają -1 .

Na przykład, aby sprawdzić, czy liczba zmiennoprzecinkowa x < y , zaleca się użycie cmpg-float ; wynik -1 oznacza, że ​​test był prawdziwy, a pozostałe wartości wskazują, że był fałszywy z powodu prawidłowego porównania lub dlatego, że jedną z wartości była NaN .

32..37 22t if- test vA, vB, +CCCC
32: jeśli-równe
33: jeśli-ne
34: jeśli-lt
35: jeśli-ge
36: jeśli-gt
37: jeśli-le
A: pierwszy rejestr do przetestowania (4 bity)
B: drugi rejestr do testowania (4 bity)
C: podpisane przesunięcie gałęzi (16 bitów)
Odgałęzienie do podanego miejsca docelowego, jeśli podane wartości dwóch rejestrów są porównywane zgodnie ze specyfikacją.

Uwaga: Przesunięcie rozgałęzienia nie może wynosić 0 . (Pętla spinowa może być legalnie skonstruowana albo przez rozgałęzienie wokół wstecznego goto , albo przez włączenie nop jako celu przed rozgałęzieniem.)

38..3d 21t if- test z vAA, +BBBB
38: if-eqz
39: jeśli-nez
3a: jeśli-ltz
3b: jeśli-gez
3c: jeśli-gtz
3d: jeśli-lez
A: zarejestruj się do przetestowania (8 bitów)
B: podpisane przesunięcie gałęzi (16 bitów)
Odgałęzienie do podanego miejsca docelowego, jeśli wartość danego rejestru jest porównywana z 0, jak określono.

Uwaga: Przesunięcie rozgałęzienia nie może wynosić 0 . (Pętla spinowa może być legalnie skonstruowana albo przez rozgałęzienie wokół wstecznego goto , albo przez włączenie nop jako celu przed rozgałęzieniem.)

3e..43 10x (nie używany) (nie używany)
44..51 23x arrayop vAA, vBB, vCC
44: wiek
45: w całym wieku
46: obiekt-get
47: aget-boolean
48: aget-bajt
49: aget-char
4a: krótki wiek
4b: aput
4c: w całym aput
4d: obiekt aput
4e: aput-boolean
4f: bajt danych
50: aput-char
51: aput-krótki
A: rejestr wartości lub para; może być źródłem lub celem (8 bitów)
B: rejestr tablicowy (8 bitów)
C: rejestr indeksowy (8 bitów)
Wykonać operację na zidentyfikowanej tablicy na zidentyfikowanym indeksie danej tablicy, ładując lub zapisując do rejestru wartości.
52.5f 22c I instanceop vA, vB, pole@CCCC
52: iget
53: iget-szeroki
54: iget-obiekt
55: iget-boolean
56: iget-bajt
57: iget-char
58: iget-krótki
59: iput
5a: cały iput
5b: iput-obiekt
5c: iput-boolean
5d: iput-bajt
5e: iput-char
5f: iput-krótki
A: rejestr wartości lub para; może być źródłem lub celem (4 bity)
B: rejestr obiektów (4 bity)
C: indeks referencyjny pola instancji (16 bitów)
Wykonaj operację na polu instancji zidentyfikowanego obiektu ze zidentyfikowanym polem, ładując lub zapisując do rejestru wartości.

Uwaga: Te kody operacyjne są rozsądnymi kandydatami do łączenia statycznego, zmieniając argument pola tak, aby był bardziej bezpośrednim przesunięciem.

60..6d 21c s staticop vAA, pole@BBBB
60: sget
61: sget-szeroki
62: obiekt-sget
63: sget-boolean
64: sget-bajt
65: sget-char
66: sget-krótki
67: pluć
68: sput-wide
69: pluć-obiekt
6a: splut-boolean
6b: bajt danych
6c: sput-char
6d: zwarcie-krótki
A: rejestr wartości lub para; może być źródłem lub celem (8 bitów)
B: indeks referencyjny pola statycznego (16 bitów)
Wykonaj operację na polu statycznym zidentyfikowanego obiektu ze zidentyfikowanym polem statycznym, ładując lub zapisując do rejestru wartości.

Uwaga: Te kody operacyjne są rozsądnymi kandydatami do łączenia statycznego, zmieniając argument pola tak, aby był bardziej bezpośrednim przesunięciem.

6e..72 35c inwokuj- uprzejmy {vC, vD, vE, vF, vG}, meth@BBBB
6e: invoke-virtual
6f: invoke-super
70: wywołanie-bezpośrednie
71: wywołanie statyczne
72: interfejs wywołania
A: liczba słów argumentów (4 bity)
B: indeks referencyjny metody (16 bitów)
C..G: rejestry argumentów (każdy 4 bity)
Wywołaj wskazaną metodę. Wynik (jeśli istnieje) może być przechowywany z odpowiednim wariantem move-result* jako kolejna instrukcja.

invoke-virtual służy do wywoływania normalnej metody wirtualnej (metody, która nie jest private , static ani final , a także nie jest konstruktorem).

Gdy method_id odwołuje się do metody klasy bez interfejsu, invoke-super służy do wywołania metody wirtualnej najbliższej nadklasy (w przeciwieństwie do tej z tym samym method_id w klasie wywołującej). Obowiązują te same ograniczenia metod, co w przypadku invoke-virtual .

W plikach Dex w wersji 037 lub nowszej, jeśli method_id odnosi się do metody interfejsu, invoke-super służy do wywołania najbardziej specyficznej, nie nadpisanej wersji tej metody zdefiniowanej w tym interfejsie. Obowiązują te same ograniczenia metod, co w przypadku invoke-virtual . W plikach Dex wcześniejszych niż wersja 037 posiadanie interfejsu method_id jest niedozwolone i niezdefiniowane.

invoke-direct służy do wywoływania static metody bezpośredniej (tj. metody instancji, która ze swej natury jest niemożliwa do nadpisania, a mianowicie private metody instancji lub konstruktora).

invoke-static służy do wywołania metody static (która jest zawsze uważana za metodę bezpośrednią).

invoke-interface służy do wywołania metody interface , czyli na obiekcie, którego konkretna klasa nie jest znana, przy użyciu method_id , która odwołuje się do interface .

Uwaga: Te kody operacji są rozsądnymi kandydatami do łączenia statycznego, zmieniając argument metody na bardziej bezpośrednie przesunięcie (lub ich parę).

73 10x (nie używany) (nie używany)
74..78 3rc invoke- kind /range {vCCCC .. vNNNN}, met@BBBB
74: wywołanie-wirtualne/zakres
75: wywołanie-super/zakres
76: wywołanie-bezpośrednie/zakres
77: wywołanie-statyczne/zakres
78: interfejs wywołania/zakres
A: liczba słów argumentów (8 bitów)
B: indeks referencyjny metody (16 bitów)
C: rejestr pierwszego argumentu (16 bitów)
N = A + C - 1
Wywołaj wskazaną metodę. Zobacz pierwszy opis invoke- kind powyżej, aby uzyskać szczegółowe informacje, zastrzeżenia i sugestie.
79..7a 10x (nie używany) (nie używany)
7b..8f 12x unop vA, vB
7b: ujemna-int
7c: nie-int
7d: neg-długi
7e: niedługi
7f: neg-float
80: neg-podwójny
81: między-do-długi
82: zmiennoprzecinkowa
83: między-do-podwójnie
84: długo-do-int
85: długi do pływania
86: długi do podwojenia
87: pływak do wewnątrz
88: pływający na długi
89: zmiennoprzecinkowa-podwójna
8a: podwójne do wewnątrz
8b: od podwójnego do długiego
8c: podwójna do pływania
8d: zamienianie na bajt
8e: zamień na znak
8f: od wewnątrz do skróconego
A: rejestr docelowy lub para (4 bity)
B: rejestr źródłowy lub para (4 bity)
Wykonaj zidentyfikowaną operację jednoargumentową na rejestrze źródłowym, przechowując wynik w rejestrze docelowym.
90..po 23x binop vAA, vBB, vCC
90: dodatek
91: sub-int
92: multi-int
93: div-int
94: rem-int
95: i-int
96: lub-int
97: xor-int
98: shl-int
99: kr-int
9a: ushr-int
9b: add-long
9c: sub-długie
9d: mul-long
9e: div-long
9f: rem-long
a0: i-długie
a1: lub-długi
a2: xor-long
a3: shl-long
a4: shr-long
a5: ushr-długi
a6: dodaj-float
a7: sub-float
a8: multi-float
a9: div-float
aa: rem-float
ab: add-double
ac: sub-double
reklama: mul-double
ae: div-double
af: rem-double
A: rejestr docelowy lub para (8 bitów)
B: pierwszy rejestr źródłowy lub para (8 bitów)
C: drugi rejestr źródłowy lub para (8 bitów)
Wykonaj zidentyfikowaną operację binarną na dwóch rejestrach źródłowych, przechowując wynik w rejestrze docelowym.

Uwaga: W przeciwieństwie do innych operacji matematycznych -long (które pobierają pary rejestrów dla pierwszego i drugiego źródła), shl-long , shr- shr-long i ushr-long pobierają parę rejestrów dla swojego pierwszego źródła (wartość do przesunięcia ), ale pojedynczy rejestr dla drugiego źródła (odległość przesunięcia).

b0..cf 12x binop /2addr vA, vB
b0: dodatek/2addr
b1: sub-int/2addr
b2: mul-int/2addr
b3: div-int/2addr
b4: rem-int/2addr
b5: i-int/2addr
b6: lub-int/2addr
b7: xor-int/2addr
b8: shl-int/2addr
b9: shr-int/2addr
ba: ushr-int/2addr
bb: add-long/2addr
bc: sub-long/2addr
bd: mul-long/2addr
być: div-long/2addr
bf: rem-long/2addr
c0: i-długi/2addr
c1: lub-długi/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
cc: sub-double/2addr
cd: mul-double/2addr
ce: div-double/2addr
por: rem-double/2addr
A: docelowy i pierwszy rejestr źródłowy lub para (4 bity)
B: drugi rejestr źródłowy lub para (4 bity)
Wykonaj zidentyfikowaną operację binarną na dwóch rejestrach źródłowych, przechowując wynik w pierwszym rejestrze źródłowym.

Uwaga: W przeciwieństwie do innych operacji matematycznych -long/2addr (które pobierają pary rejestrów zarówno dla miejsca docelowego/pierwszego źródła, jak i drugiego źródła), shl-long/2addr , shr shr-long/2addr i ushr-long/2addr pobierają rejestr para dla ich miejsca docelowego/pierwszego źródła (wartość do przesunięcia), ale pojedynczy rejestr dla drugiego źródła (odległość przesunięcia).

d0..d7 22s binop /lit16 vA, vB, #+CCCC
d0: dodatek/lit16
d1: rsub-int (odwrotne odejmowanie)
d2: mul-int/lit16
d3: div-int/lit16
d4: rem-int/lit16
d5: i-int/lit16
d6: or-int/lit16
d7: xor-int/lit16
A: rejestr docelowy (4 bity)
B: rejestr źródłowy (4 bity)
C: sign int stała (16 bitów)
Wykonaj wskazaną operację binarną na wskazanym rejestrze (pierwszy argument) i wartości literału (drugi argument), przechowując wynik w rejestrze docelowym.

Uwaga: rsub-int nie ma sufiksu, ponieważ ta wersja jest głównym opcodem swojej rodziny. Zobacz także poniżej, aby uzyskać szczegółowe informacje na temat jego semantyki.

d8..e2 22b binop /lit8 vAA, vBB, #+CC
d8: dodatek/lit8
d9: rsub-int/lit8
da: mul-int/lit8
db: div-int/lit8
dc: rem-int/lit8
dd: i-int/lit8
de: or-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: shr-int/lit8
e2: ushr-int/lit8
A: rejestr docelowy (8 bitów)
B: rejestr źródłowy (8 bitów)
C: sign int stała (8 bitów)
Wykonaj wskazaną operację binarną na wskazanym rejestrze (pierwszy argument) i wartości literału (drugi argument), przechowując wynik w rejestrze docelowym.

Uwaga: poniżej znajdziesz szczegółowe informacje na temat semantyki rsub-int .

e3..f9 10x (nie używany) (nie używany)
fa 45cc wywołaj polimorficzny {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: liczba słów argumentów (4 bity)
B: indeks referencyjny metody (16 bitów)
C: odbiornik (4 bity)
D..G: rejestry argumentów (każdy 4 bity)
H: indeks referencyjny prototypu (16 bitów)
Wywołaj wskazaną metodę polimorficzną sygnatury. Wynik (jeśli istnieje) może być przechowywany z odpowiednim wariantem move-result* jako kolejna instrukcja.

Odwołanie do metody musi odnosić się do sygnaturowej metody polimorficznej, takiej jak java.lang.invoke.MethodHandle.invoke lub java.lang.invoke.MethodHandle.invokeExact .

Odbiorca musi być obiektem obsługującym wywoływaną metodę polimorficzną sygnatury.

Odwołanie do prototypu opisuje podane typy argumentów i oczekiwany typ zwracany.

invoke-polymorphic kod bajtowy może zgłaszać wyjątki podczas wykonywania. Wyjątki są opisane w dokumentacji API dla wywoływanej metody polimorficznej sygnatury.

Obecny w plikach Dex od wersji 038 i nowszych.
fb 4rcc wywołaj polimorficzny/zakres {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: liczba słów argumentów (8 bitów)
B: indeks referencyjny metody (16 bitów)
C: odbiornik (16 bitów)
H: indeks referencyjny prototypu (16 bitów)
N = A + C - 1
Wywołaj wskazany uchwyt metody. Zobacz opis invoke-polymorphic powyżej, aby uzyskać szczegółowe informacje.

Obecny w plikach Dex od wersji 038 i nowszych.
fc 35c invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB A: liczba słów argumentów (4 bity)
B: indeks referencyjny strony wywołania (16 bitów)
C..G: rejestry argumentów (każdy 4 bity)
Rozwiązuje i wywołuje wskazane miejsce wywołania. Wynik wywołania (jeśli istnieje) może być przechowywany z odpowiednim wariantem move-result* jako kolejna instrukcja.

Ta instrukcja jest wykonywana w dwóch fazach: rozpoznanie miejsca połączenia i wywołanie miejsca połączenia.

Rozpoznawanie witryny wywołań sprawdza, czy wskazana witryna wywołań ma skojarzone wystąpienie java.lang.invoke.CallSite . Jeśli nie, metoda konsolidatora ładowania początkowego dla wskazanej witryny wywołania jest wywoływana przy użyciu argumentów obecnych w pliku DEX (zobacz call_site_item ). Metoda konsolidatora ładowania początkowego zwraca instancję java.lang.invoke.CallSite , która zostanie następnie powiązana ze wskazaną witryną wywołań, jeśli nie istnieje żadne powiązanie. Inny wątek mógł już jako pierwszy utworzyć skojarzenie, a jeśli tak, wykonanie instrukcji jest kontynuowane z pierwszą skojarzoną instancją java.lang.invoke.CallSite .

Wywołanie witryny wywołania jest wykonywane na celu java.lang.invoke.MethodHandle rozwiązanej instancji java.lang.invoke.CallSite . Cel jest wywoływany tak, jakby wykonywał invoke-polymorphic (opisany powyżej) przy użyciu uchwytu metody i argumentów instrukcji invoke-custom jako argumentów dokładnego uchwytu metody.

Wyjątki zgłoszone przez metodę konsolidatora bootstrap są opakowane w java.lang.BootstrapMethodError . BootstrapMethodError jest również zgłaszany, jeśli:
  • metoda konsolidatora ładowania początkowego nie zwraca instancji java.lang.invoke.CallSite .
  • zwrócony java.lang.invoke.CallSite ma cel uchwytu metody o null .
  • cel uchwytu metody nie jest żądanego typu.
Obecny w plikach Dex od wersji 038 i nowszych.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: liczba słów argumentów (8 bitów)
B: indeks referencyjny strony wywołania (16 bitów)
C: rejestr pierwszego argumentu (16-bitowy)
N = A + C - 1
Rozwiąż i wywołaj witrynę połączeń. Zobacz opis invoke-custom powyżej, aby uzyskać szczegółowe informacje.

Obecny w plikach Dex od wersji 038 i nowszych.
np. 21c const-method-handle vAA, method_handle@BBBB A: rejestr docelowy (8 bitów)
B: indeks uchwytu metody (16 bitów)
Przenieś odwołanie do uchwytu metody określonego przez dany indeks do określonego rejestru.

Obecny w plikach Dex od wersji 039 i nowszych.
ff 21c vAA typu const-method, proto@BBBB A: rejestr docelowy (8 bitów)
B: odniesienie do prototypu metody (16 bitów)
Przenieś odwołanie do prototypu metody określonego przez dany indeks do określonego rejestru.

Obecny w plikach Dex od wersji 039 i nowszych.

pakowany-switch-payload format

Nazwa Format Opis
ident krótki = 0x0100 identyfikacja pseudo-kodu operacyjnego
rozmiar skrócić liczba wpisów w tabeli
pierwszy_klucz int pierwsza (i najniższa) wartość przypadku przełącznika
cele int[] lista docelowych gałęzi względnych size . Cele są zależne od adresu kodu operacji przełącznika, a nie z tej tabeli.

Uwaga: Całkowita liczba jednostek kodu dla wystąpienia tej tabeli to (size * 2) + 4 .

format sparse-switch-payload

Nazwa Format Opis
ident krótki = 0x0200 identyfikacja pseudo-kodu operacyjnego
rozmiar skrócić liczba wpisów w tabeli
Klucze int[] lista kluczowych wartości size , posortowana od najniższej do najwyższej
cele int[] lista docelowych gałęzi względnych względem size , z których każdy odpowiada wartości klucza w tym samym indeksie. Cele są zależne od adresu kodu operacji przełącznika, a nie z tej tabeli.

Uwaga: Całkowita liczba jednostek kodu dla wystąpienia tej tabeli to (size * 4) + 2 .

format wypełnienia tablicy danych-dane

Nazwa Format Opis
ident krótki = 0x0300 identyfikacja pseudo-kodu operacyjnego
szerokość_elementu skrócić liczba bajtów w każdym elemencie
rozmiar nieskończoność liczba elementów w tabeli
dane ubajt[] wartości danych

Uwaga: Całkowita liczba jednostek kodu dla wystąpienia tej tabeli wynosi (size * element_width + 1) / 2 + 4 .

Matematyczne szczegóły operacji

Uwaga: Operacje zmiennoprzecinkowe muszą być zgodne z regułami IEEE 754, wykorzystującymi zaokrąglenie do najbliższego i stopniowe niedopełnienie, chyba że określono inaczej.

Kod operacji C Semantyka Uwagi
negacja int32a;
int32 wynik = -a;
Jednoargumentowe dwójki-uzupełnianie.
nie-int int32a;
int32 wynik = ~a;
Jednoargumentowe komplementy.
neg-długi int64a;
int64 wynik = -a;
Jednoargumentowe dwójki-uzupełnianie.
nie długo int64a;
int64 wynik = ~a;
Jednoargumentowe komplementy.
neg-float pływać;
wynik zmiennoprzecinkowy = -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 .