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 rozmiar ramek jest stały podczas tworzenia. Każda ramka składa się z określonej liczby rejestrów (określonej przez metodę) oraz wszelkich danych dodatkowych potrzebnych do wykonania metody, takich jak (ale nie wyłącznie) licznik programu i odniesienie do pliku
.dex
zawierającego metodę . - W przypadku stosowania do wartości bitowych (takich jak liczby całkowite i liczby zmiennoprzecinkowe) rejestry są uznawane za szerokie na 32 bity. Dla wartości 64-bitowych używane są sąsiednie pary rejestrów. Nie ma wymogu wyrównania dla par rejestrów.
- Rejestry używane do odniesień do obiektów są uważane za wystarczająco szerokie, aby pomieścić dokładnie jedno takie odniesienie.
- Jeśli chodzi o reprezentację bitową,
(Object) null == (int) 0
. - N argumentów metody ląduje w kolejności w ostatnich N rejestrach ramki wywołania metody. Szerokie argumenty zużywają dwa rejestry. Do metod instancji przekazywane jest odwołanie
this
jako pierwszy argument.
- Maszyna jest oparta na rejestrach, a rozmiar ramek jest stały podczas tworzenia. Każda ramka składa się z określonej liczby rejestrów (określonej przez metodę) oraz wszelkich danych dodatkowych potrzebnych do wykonania metody, takich jak (ale nie wyłącznie) licznik programu i odniesienie do pliku
- Jednostką pamięci w strumieniu instrukcji jest 16-bitowa wielkość bez znaku. Niektóre bity w niektórych instrukcjach są ignorowane / muszą wynosić zero.
- Instrukcje nie są bezpodstawnie ograniczone do określonego typu. Na przykład instrukcje, które przesuwają wartości rejestrów 32-bitowych bez interpretacji, nie muszą określać, czy przesuwają liczby całkowite, czy zmiennoprzecinkowe.
- Istnieją oddzielnie wyliczane i indeksowane pule stałe zawierające odniesienia do ciągów, typów, pól i metod.
- Dane literału bitowego są reprezentowane w strumieniu instrukcji.
- Ponieważ w praktyce rzadko zdarza się, aby metoda wymagała więcej niż 16 rejestrów, a potrzeba więcej niż ośmiu rejestrów jest dość powszechna, wiele instrukcji ogranicza się tylko do adresowania pierwszych 16 rejestrów. Jeśli jest to racjonalnie możliwe, instrukcje umożliwiają odwoływanie się do maksymalnie 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
catch-all, które mogą adresować rejestry z zakresuv0
–v65535
. W przypadkach, gdy nie jest dostępny wariant instrukcji adresowania żądanego rejestru, oczekuje się, że zawartość rejestru zostanie przeniesiona z rejestru pierwotnego do rejestru dolnego (przed operacją) i/lub przeniesiona z rejestru dolnego wyniku do rejestru wysokiego zarejestruj się (po operacji). - Istnieje kilka „pseudoinstrukcji”, które służą 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
). Z takimi instrukcjami nie można nigdy spotkać się w trakcie normalnego wykonywania. Ponadto instrukcje muszą być umieszczone w parzystych przesunięciach kodu bajtowego (tj. wyrównane 4-bajtowo). Aby spełnić ten wymóg, narzędzia generujące dex muszą emitować dodatkową instrukcjęnop
jako odstępnik, jeśli w przeciwnym razie taka instrukcja byłaby niewyrównana. Wreszcie, chociaż nie jest to wymagane, oczekuje się, że większość narzędzi zdecyduje się na emisję tych instrukcji na końcach metod, ponieważ w przeciwnym razie prawdopodobnie potrzebne byłyby dodatkowe instrukcje do ich rozgałęzienia. - Po zainstalowaniu w działającym systemie niektóre instrukcje mogą zostać zmienione, zmieniając ich format, w ramach optymalizacji statycznego łączenia w czasie instalacji. Ma to na celu umożliwienie szybszego wykonania, gdy znane jest powiązanie. Sugerowane warianty można znaleźć w powiązanym dokumencie dotyczącym formatów instrukcji . Słowo „sugerowane” zostało użyte rozsądnie; ich wdrożenie nie jest obowiązkowe.
- Składnia człowieka i mnemonika:
- Porządkowanie argumentów według źródła i źródła.
- Niektóre kody operacji mają jednoznaczny przyrostek nazwy wskazujący typ (y), na których działają:
- Ogólne 32-bitowe kody operacji są nieoznaczone.
- Ogólne 64-bitowe kody operacji mają przyrostek
-wide
. - Do kodów operacji specyficznych dla typu dodawany jest przyrostek określający ich typ (lub prosty skrót), jeden z następujących:
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- Niektóre kody operacji mają ujednoznaczniający przyrostek umożliwiający rozróżnienie w przeciwnym razie identycznych operacji, które mają różne układy instrukcji lub opcje. Te przyrostki są oddzielone od głównych nazw ukośnikiem („
/
”) i istnieją głównie po to, aby zapewnić mapowanie jeden do jednego ze stałymi statycznymi w kodzie, który generuje i interpretuje pliki wykonywalne (to znaczy w celu zmniejszenia niejednoznaczności dla ludzi). - W niniejszych opisach szerokość wartości (wskazująca np. zakres stałej lub liczbę możliwych do adresowania rejestrów) jest podkreślana poprzez użycie znaku przypadającego na cztery bity szerokości.
- Przykładowo w instrukcji „
move-wide/from16 vAA, vBBBB
”:- „
move
” to podstawowy kod operacji, wskazujący podstawową operację (przesunięcie wartości rejestru). - „
wide
” to przyrostek nazwy wskazujący, że operuje na szerokich (64-bitowych) danych. - „
from16
” to przyrostek kodu operacji, wskazujący wariant, który jako źródło ma odniesienie do rejestru 16-bitowego. - „
vAA
” to rejestr docelowy (co wynika z operacji; ponownie obowiązuje zasada, że argumenty docelowe są zawsze podawane jako pierwsze), który musi należeć do zakresuv0
–v255
. - „
vBBBB
” to rejestr źródłowy, który musi należeć do zakresuv0
–v65535
.
- „
- Zobacz dokument dotyczący formatów instrukcji, aby uzyskać więcej szczegółów na temat różnych formatów instrukcji (wymienionych w sekcji „Opcje i format”), a także szczegółów na temat składni kodu operacji.
- Zobacz dokument formatu pliku
.dex
, aby uzyskać więcej szczegółów na temat tego, gdzie kod bajtowy pasuje do szerszego obrazu.
Podsumowanie zestawu kodów bajtowych
Operacje i formatowanie | Mnemonika / składnia | Argumenty | Opis |
---|---|---|---|
00 10x | nie | Cykle odpadów. Uwaga: pseudoinstrukcje przenoszące dane są oznaczone tym kodem operacji, w którym to przypadku starszy bajt jednostki kodu operacji wskazuje naturę danych. Zobacz „Format | |
01 12x | przesuń vA, vB | A: rejestr docelowy (4 bity)B: rejestr źródłowy (4 bity) | Przenieś zawartość jednego rejestru nieobiektowego do innego. |
02 22x | przesuń/z 16 vAA, vBBBB | A: rejestr docelowy (8 bitów)B: rejestr źródłowy (16 bitów) | Przenieś zawartość jednego rejestru nieobiektowego do innego. |
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 innego. |
04 12x | poruszaj się szeroko 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: Przejście z |
05 22x | move-wide/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 przypadku |
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 przypadku |
07 12x | przesuń obiekt vA, vB | A: rejestr docelowy (4 bity)B: rejestr źródłowy (4 bity) | Przenieś zawartość jednego rejestru zawierającego obiekty do innego. |
08 22x | move-object/from16 vAA, vBBBB | A: rejestr docelowy (8 bitów)B: rejestr źródłowy (16 bitów) | Przenieś zawartość jednego rejestru zawierającego obiekty do innego. |
09 32x | move-object/16 vAAAA, vBBBB | A: rejestr docelowy (16 bitów)B: rejestr źródłowy (16 bitów) | Przenieś zawartość jednego rejestru zawierającego obiekty do innego. |
0a 11x | wynik ruchu vAA | A: rejestr docelowy (8 bitów) | Przenieś jednowyrazowy, nieobiektowy wynik ostatniego invoke- kind do wskazanego rejestru. Należy to zrobić jako instrukcję bezpośrednio po invoke- kind którego wynik (jednowyrazowy, nieobiektowy) nie powinien być ignorowany; gdziekolwiek indziej jest nieważne. |
0b 11x | vAA w całym wyniku ruchu | A: para rejestrów docelowych (8 bitów) | Przenieś wynik podwójnego słowa ostatniego invoke- kind do wskazanej pary rejestrów. Należy to zrobić jako instrukcję bezpośrednio po invoke- kind którego wynik (podwójne słowo) nie powinien być ignorowany; gdziekolwiek indziej jest nieważne. |
0c 11x | przesuń obiekt-wynikowy vAA | A: rejestr docelowy (8 bitów) | Przenieś wynik obiektu ostatniego invoke- kind do wskazanego rejestru. Należy to wykonać jako instrukcję bezpośrednio po invoke- kind lub filled-new-array której wynik (obiektu) nie powinien być ignorowany; gdziekolwiek indziej jest nieważne. |
0d 11x | wyjątek ruchu vAA | A: rejestr docelowy (8 bitów) | Zapisz właśnie przechwycony wyjątek w podanym rejestrze. Musi to być pierwsza instrukcja dowolnej procedury obsługi wyjątku, której przechwycony wyjątek nie ma być ignorowany, a instrukcja ta może zawsze występować tylko jako pierwsza instrukcja obsługi wyjątku; gdziekolwiek indziej jest nieważne. |
0e 10x | zwrot-nieważny | Powrót z metody void . | |
0f 11x | zwrócić vAA | A: rejestr wartości zwracanej (8 bitów) | Powrót z metody nie zwracającej wartości obiektowej o pojedynczej szerokości (32-bitowej). |
10 11x | vAA o szerokim zakresie zwrotu | A: zwracana para rejestrów wartości (8 bitów) | Powrót z metody zwracającej wartość o podwójnej szerokości (64-bitowej). |
11 11x | obiekt zwracany vAA | A: rejestr wartości zwracanej (8 bitów) | Powrót z metody zwracającej obiekt. |
12 11n | stała/4 vA, #+B | A: rejestr docelowy (4 bity)B: podpisany int (4 bity) | Przenieś podaną wartość literału (ze znakiem rozszerzonym do 32 bitów) do określonego rejestru. |
13 21s | stała/16 vAA, #+BBBB | A: rejestr docelowy (8 bitów)B: podpisany int (16 bitów) | Przenieś podaną wartość literału (ze znakiem rozszerzonym do 32 bitów) do określonego rejestru. |
14 31i | stała vAA, #+BBBBBBBB | A: rejestr docelowy (8 bitów)B: dowolna stała 32-bitowa | Przenieś podaną wartość literału do określonego rejestru. |
15 21h | stała/wysoka16 vAA, #+BBBB0000 | A: rejestr docelowy (8 bitów)B: podpisany int (16 bitów) | Przenieś podaną wartość literału (z prawej strony zera rozszerzonego do 32 bitów) do określonego rejestru. |
16 21s | const-wide/16 vAA, #+BBBB | A: rejestr docelowy (8 bitów)B: podpisany int (16 bitów) | Przenieś podaną wartość literału (ze znakiem rozszerzonym do 64 bitów) do określonej pary rejestrów. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: rejestr docelowy (8 bitów)B: podpisany int (32 bity) | Przenieś podaną wartość literału (ze znakiem rozszerzonym do 64 bitów) do określonej pary rejestrów. |
18 51l | const-wide vAA, #+BBBBBBBBBBBBBB | A: rejestr docelowy (8 bitów)B: dowolna stała podwójnej szerokości (64-bitowa). | Przenieś podaną wartość literału do określonej pary rejestrów. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: rejestr docelowy (8 bitów)B: podpisany int (16 bitów) | Przenieś podaną wartość literału (z prawej strony zera rozszerzoną 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 | const-klasa vAA, typ@BBBB | A: rejestr docelowy (8 bitów)B: wpisz indeks | Przenieś odwołanie do klasy określonej przez dany indeks do określonego rejestru. W przypadku, gdy wskazany typ jest pierwotny, zostanie zapisane odwołanie do zdegenerowanej klasy typu pierwotnego. |
1d 11x | monitor-wprowadź vAA | A: rejestr nośny odniesienia (8 bitów) | Zdobądź monitor dla wskazanego obiektu. |
1e 11x | wyjście monitora vAA | A: rejestr nośny odniesienia (8 bitów) | Zwolnij monitor dla wskazanego obiektu. Uwaga: Jeśli ta instrukcja ma zgłosić wyjątek, musi to zrobić tak, jakby komputer przekroczył już tę instrukcję. Przydatne może być myślenie o tym jako o pomyślnym wykonaniu instrukcji (w pewnym sensie) i wyjątku zgłoszonym po instrukcji, ale zanim następna będzie miała szansę na wykonanie. Ta definicja umożliwia metodzie użycie bloku catch-all (np. |
1f 21c | check-cast vAA, typ@BBBB | A: rejestr nośny odniesienia (8 bitów)B: indeks typu (16 bitów) | Zgłoś ClassCastException , jeśli odwołanie w danym rejestrze nie może zostać rzutowane na wskazany typ. Uwaga: Ponieważ |
20 22c | instancja vA, vB, typ@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 wskazana referencja jest instancją danego typu, lub 0 jeśli nie. Uwaga: Ponieważ |
21 12x | długość tablicy vA, vB | A: rejestr docelowy (4 bity)B: rejestr nośny tablicy referencyjnej (4 bity) | Zapisz w podanym rejestrze docelowym długość wskazanej tablicy, we wpisach |
22 21c | nowa instancja vAA, typ@BBBB | A: rejestr docelowy (8 bitów)B: wpisz indeks | Skonstruuj nową instancję wskazanego typu, przechowując odwołanie do niej w miejscu docelowym. Typ musi odnosić się do klasy niebędącej tablicą. |
23 22c | nowa tablica vA, vB, typ@CCCC | A: rejestr docelowy (4 bity)B: rejestr wielkościC: wpisz indeks | Skonstruuj nową tablicę wskazanego typu i rozmiaru. Typ musi być typem tablicowym. |
24 35c | wypełniona-nowa-tablica {vC, vD, vE, vF, vG}, typ@BBBB | A: rozmiar tablicy i liczba słów argumentu (4 bity)B: indeks typu (16 bitów)C..G: rejestry argumentów (po 4 bity) | Skonstruuj tablicę danego typu i rozmiaru, wypełniając ją dostarczoną zawartością. Typ musi być typem tablicowym. Zawartość tablicy musi składać się z jednego słowa (to znaczy nie może zawierać tablic typu long ani double , ale dopuszczalne są typy referencyjne). Skonstruowana instancja jest przechowywana jako „wynik” w taki sam sposób, w jaki instrukcje wywołania metody przechowują swoje wyniki, zatem skonstruowana instancja musi zostać przeniesiona do rejestru z bezpośrednio następującą instrukcją move-result-object (jeśli ma być użyta ). |
25 3rc | wypełniona-nowa-tablica/zakres {vCCCC .. vNNNN}, typ@BBBB | A: rozmiar tablicy i liczba słów argumentu (8 bitów)B: indeks typu (16 bitów)C: rejestr pierwszego argumentu (16 bitów)N = A + C - 1 | Skonstruuj tablicę danego typu i rozmiaru, wypełniając ją dostarczoną zawartością. Wyjaśnienia i ograniczenia są takie same jak w filled-new-array opisanej powyżej. |
26 31t | fill-array-data vAA, +BBBBBBBB (z dodatkowymi danymi określonymi poniżej w „formacie fill-array-data-payload ”) | A: odwołanie do tablicy (8 bitów)B: przesunięcie „gałęzi” ze znakiem do pseudoinstrukcji danych tabeli (32 bity) | Wypełnij podaną tablicę wskazanymi danymi. Odniesienie musi odnosić się do tablicy prymitywów, a tabela danych musi odpowiadać jej typowi 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ż tabela, a jeśli tak, ustawiane są tylko początkowe elementy tablicy, resztę pozostawiając samą. |
27 11x | rzuć vAA | A: rejestr zawierający wyjątki (8 bitów) | Zgłoś wskazany wyjątek. |
28 10t | mam +AA | A: przesunięcie gałęzi ze znakiem (8 bitów) | Bezwarunkowy skok do wskazanej instrukcji. Uwaga: Przesunięcie gałęzi nie może wynosić |
29 20t | goto/16 +AAAA | A: przesunięcie gałęzi ze znakiem (16 bitów) | Bezwarunkowy skok do wskazanej instrukcji. Uwaga: Przesunięcie gałęzi nie może wynosić |
2a 30t | goto/32 +AAAAAAAA | A: przesunięcie gałęzi ze znakiem (32 bity) | Bezwarunkowy skok do wskazanej instrukcji. |
2b 31t | pakiet-switch vAA, +BBBBBBBB (z dodatkowymi danymi określonymi poniżej w „formacie packed-switch-payload ”) | A: zarejestruj się, aby przetestowaćB: przesunięcie „gałęzi” ze znakiem do pseudoinstrukcji danych tabeli (32 bity) | Przejdź do nowej instrukcji w oparciu o wartość w danym rejestrze, korzystając z tabeli przesunięć odpowiadających 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 „formacie sparse-switch-payload ”) | A: zarejestruj się, aby przetestowaćB: przesunięcie „gałęzi” ze znakiem do pseudoinstrukcji danych tabeli (32 bity) | Przejdź do nowej instrukcji w oparciu o wartość w danym rejestrze, korzystając z uporządkowanej tabeli par wartości-przesunięcie lub przejdź do następnej instrukcji, jeśli nie ma dopasowania. |
2d..31 23x | cmp rodzaj vAA, vBB, vCC 2d: cmpl-float (odchylenie lt) 2e: cmpg-float (odchylenie gt) 2f: cmpl-double (lt odchylenie) 30: cmpg-double (odchylenie gt) 31: długość cm | A: rejestr docelowy (8 bitów)B: pierwszy rejestr źródłowy lub paraC: drugi rejestr źródłowy lub para | Wykonaj wskazane porównanie zmiennoprzecinkowe lub long , 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 odchylenie” zwracają 1 dla porównań NaN , a instrukcje „lt odchylenie” zwracają -1 . Na przykład, aby sprawdzić, czy zmiennoprzecinkowy |
32..37 22t | if- test vA, vB, +CCCC 32: jeśli-równ 33: jeśli-nie 34: jeśli-lt 35: jeśli-ge 36: jeśli-gt 37: jeśli-le | A: pierwszy rejestr do testowania (4 bity)B: drugi rejestr do testowania (4 bity)C: przesunięcie gałęzi ze znakiem (16 bitów) | Przejdź do podanego miejsca docelowego, jeśli wartości danych dwóch rejestrów zostaną porównane zgodnie ze specyfikacją. Uwaga: Przesunięcie gałęzi nie może wynosić |
38..3d 21t | if- test z vAA, +BBBB 38: jeśli-równ 39: jeśli-nez 3a: jeśli-ltz 3b: jeśli-gez 3c: jeśli-gtz 3d: jeśli-lez | A: zarejestruj się, aby przetestować (8 bitów)B: przesunięcie gałęzi ze znakiem (16 bitów) | Przejdź do podanego miejsca docelowego, jeśli wartość danego rejestru porównuje się z 0, jak określono. Uwaga: Przesunięcie gałęzi nie może wynosić |
3e..43 10x | (nie używany) | (nie używany) | |
44..51 23x | tablica vAA, vBB, vCC 44: wiek 45: w całym wieku 46: obiekt wieku 47: wartość logiczna wieku 48: bajt wieku 49: wiek-char 4a: krótki wiek 4b: aput 4c: szeroki na aput 4d: obiekt-aput 4e: aput-boolean 4f: aput-bajt 50: aput-char 51: aput-krótki | A: rejestr wartości lub para; może być źródłem lub miejscem docelowym (8 bitów)B: rejestr tablicowy (8 bitów)C: rejestr indeksowy (8 bitów) | Wykonaj zidentyfikowaną operację na tablicy pod wskazanym indeksem danej tablicy, ładując lub zapisując do rejestru wartości. |
52..5f 22c | instancjaop vA, vB, pole@CCCC 52: iget 53: szeroki iget 54: obiekt iget 55: iget-boolean 56: bajt iget 57: iget-char 58: iget-short 59: iput 5a: obejmujący całe wejście 5b: obiekt iput 5c: iput-boolean 5d: bajt iput 5e: iput-char 5f: iput-short | A: rejestr wartości lub para; może być źródłem lub miejscem docelowym (4 bity)B: rejestr obiektowy (4 bity)C: indeks odniesienia pola instancji (16 bitów) | Wykonaj operację polową instancji zidentyfikowanego obiektu na zidentyfikowanym polu, ładując lub zapisując do rejestru wartości. Uwaga: Te kody operacji 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: szeroki 62: obiekt-sget 63: sget-boolean 64: sget-bajt 65: sget-char 66: sget-krótki 67: pluć 68: szeroka 69: obiekt plucia 6a: sput-boolean 6b: bajt sput 6c: sput-char 6d: splunięcie krótkie | A: rejestr wartości lub para; może być źródłem lub miejscem docelowym (8 bitów)B: indeks odniesienia pola statycznego (16 bitów) | Wykonaj operację pola statycznego zidentyfikowanego obiektu ze zidentyfikowanym polem statycznym, ładując lub zapisując do rejestru wartości. Uwaga: Te kody operacji są rozsądnymi kandydatami do łączenia statycznego, zmieniając argument pola tak, aby był bardziej bezpośrednim przesunięciem. |
6e..72 35c | invoke- kind {vC, vD, vE, vF, vG}, met@BBBB 6e: wywołanie-wirtualne 6f: wywołaj super 70: wywołanie bezpośrednie 71: wywołanie statyczne 72: interfejs wywołania | A: liczba słów argumentu (4 bity)B: indeks odniesienia metody (16 bitów)C..G: rejestry argumentów (po 4 bity) | Wywołaj wskazaną metodę. Wynik (jeśli istnieje) może zostać zapisany z odpowiednim wariantem move-result* jako instrukcja bezpośrednio następująca. Gdy W plikach Dex w wersji Uwaga: Te kody operacji są rozsądnymi kandydatami do łączenia statycznego, zmieniając argument metody na bardziej bezpośrednie przesunięcie (lub jego parę). |
73 10x | (nie używany) | (nie używany) | |
74..78 3rc | invoke- kind /range {vCCCC .. vNNNN}, met@BBBB 74: wywołaj-wirtualny/zakres 75: wywołanie-super/zakres 76: wywołanie bezpośrednie/zakres 77: wywołanie-statyczne/zakres 78: interfejs/zakres wywołania | A: liczba słów argumentu (8 bitów)B: indeks odniesienia metody (16 bitów)C: rejestr pierwszego argumentu (16 bitów)N = A + C - 1 | Wywołaj wskazaną metodę. Zobacz opis pierwszego 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: neg-int 7c: nie-int 7d: neg-długi 7e: niezbyt długo 7f: pływak ujemny 80: neg-podwójny 81: int-to-long 82: od wejścia do pływaka 83: int-to-double 84: długi do int 85: długi do pływania 86: długi do podwójnego 87: float-to-int 88: pływak za długi 89: float do double 8a: podwójnie do int 8b: podwójnie za długi 8c: double-to-float 8d: liczba całkowita do bajtu 8e: int-to-char 8f: od krótkiego do krótkiego | 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..af 23x | binop vAA, vBB, vCC 90: dodatek 91: podwł 92: mul-int 93: dzielenie-int 94: rem-int 95: i-int 96: lub-int 97: xor-int 98: shl-int 99: shr-int 9a: ushr-int 9b: dodatek długi 9c: niezbyt długi 9d: mul-długi 9e: długi div 9f: rem-długi a0: i-długie a1: lub-długi a2: xor-long a3: shl-long a4: shr-długi a5: długi ushr a6: add-float a7: pływak podwodny a8: mul-float a9: div-float aa: rem-float ab: dodaj-double ac: sub-podwójne 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, zapisując wynik w rejestrze docelowym. Uwaga: W przeciwieństwie do innych operacji matematycznych |
b0..por. 12x | binop /2addr vA, vB b0: dodatek/2adres b1: pod-int/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: i-int/2addr b6: or-int/2addr b7: xor-int/2addr b8: shl-int/2addr b9: shr-int/2addr ba: ushr-int/2addr bb: dodaj-długi/2addr bc: sub-długi/2addr bd: mul-long/2addr być: div-long/2addr bf: rem-long/2addr c0: i-long/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-podwójne/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, zapisując wynik w pierwszym rejestrze źródłowym. Uwaga: W przeciwieństwie do innych operacji matematycznych |
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: stała int ze znakiem (16 bitów) | Wykonaj wskazaną operację binarną na wskazanym rejestrze (pierwszy argument) i wartości literału (drugi argument), zapisując wynik w rejestrze docelowym. Uwaga: |
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: stała int ze znakiem (8 bitów) | Wykonaj wskazaną operację binarną na wskazanym rejestrze (pierwszy argument) i wartości literału (drugi argument), zapisując wynik w rejestrze docelowym. Uwaga: Poniżej znajdują się szczegółowe informacje na temat semantyki |
e3..f9 10x | (nie używany) | (nie używany) | |
tak 45cc | invoke-polimorficzny {vC, vD, vE, vF, vG}, met@BBBB, proto@HHHH | A: liczba słów argumentu (4 bity)B: indeks odniesienia metody (16 bitów)C: odbiornik (4 bity)D..G: rejestry argumentów (po 4 bity)H: indeks referencyjny prototypu (16 bitów) | Wywołaj wskazaną metodę polimorficzną podpisu. Wynik (jeśli istnieje) może zostać zapisany z odpowiednim wariantem move-result* jako instrukcja bezpośrednio następująca.Odwołanie do metody musi odnosić się do metody polimorficznej sygnatury, 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 dostarczone typy argumentów i oczekiwany typ zwracany. invoke-polymorphic może powodować wyjątki podczas wykonywania. Wyjątki opisano w dokumentacji API dla wywoływanej metody polimorficznej podpisu.Występuje w plikach Dex od wersji 038 i nowszych. |
fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH | A: liczba słów argumentu (8 bitów)B: indeks odniesienia 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. Aby uzyskać szczegółowe informacje, zobacz powyższy opis invoke-polymorphic .Występuje w plikach Dex od wersji 038 i nowszych. |
FC 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB | A: liczba słów argumentu (4 bity)B: indeks odniesienia do witryny wywoławczej (16 bitów)C..G: rejestry argumentów (po 4 bity) | Rozwiązuje i wywołuje wskazaną stronę wywołania. Wynik wywołania (jeśli istnieje) może zostać zapisany z odpowiednim wariantem move-result* jako następna instrukcja.Ta instrukcja jest wykonywana w dwóch fazach: rozpoznawanie miejsca wywołania i wywołanie miejsca wywołania. Rozpoznawanie witryny wywołań sprawdza, czy wskazana witryna wywołań ma powiązaną instancję java.lang.invoke.CallSite . Jeśli nie, wywoływana jest metoda linkera ładowania początkowego dla wskazanej strony wywołania przy użyciu argumentów znajdujących się w pliku DEX (patrz call_site_item ). Metoda linkera bootstrap 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. Być może inny wątek już jako pierwszy dokonał skojarzenia, a jeśli tak, wykonywanie instrukcji jest kontynuowane z pierwszą powiązaną instancją java.lang.invoke.CallSite .Wywołanie witryny wywołania jest wykonywane w obiekcie docelowym java.lang.invoke.MethodHandle rozwiązanej instancji java.lang.invoke.CallSite . Cel jest wywoływany tak, jakby wykonywał invoke-polymorphic (opisane powyżej) przy użyciu uchwytu metody i argumentów instrukcji invoke-custom jako argumentów dokładnego wywołania uchwytu metody.Wyjątki zgłaszane przez metodę linkera ładowania początkowego są opakowane w java.lang.BootstrapMethodError . Błąd BootstrapMethodError jest również zgłaszany, jeśli:
038 i nowszych. |
fd 3rc | invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB | A: liczba słów argumentu (8 bitów)B: indeks odniesienia do witryny wywoławczej (16 bitów)C: rejestr pierwszego argumentu (16 bitów)N = A + C - 1 | Rozwiąż problem i wywołaj witrynę połączeń. Aby uzyskać szczegółowe informacje, zobacz powyższy opis invoke-custom .Występuje w plikach Dex od wersji 038 i nowszych. |
piątek 21c | const-metoda-handle vAA, metoda_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. Występuje w plikach Dex od wersji 039 i nowszych. |
ff 21c | typ-metody stałej vAA, proto@BBBB | A: rejestr docelowy (8 bitów)B: odniesienie do prototypu metody (16 bitów) | Przenieś referencję do prototypu metody określonego przez podany indeks do określonego rejestru. Występuje w plikach Dex od wersji 039 i nowszych. |
format pakietu danych-przełącznika
Nazwa | Format | Opis |
---|---|---|
ident | ushort = 0x0100 | identyfikowanie pseudokodu operacji |
rozmiar | skrócić | ilość wpisów w tabeli |
pierwszy_klucz | wew | pierwsza (i najniższa) wartość przypadku przełącznika |
cele | int[] | lista celów oddziałów względnych pod względem size . Cele odnoszą się do adresu kodu operacji przełącznika, a nie do tej tabeli. |
Uwaga: Całkowita liczba jednostek kodu dla instancji tej tabeli wynosi (size * 2) + 4
.
format ładunku rzadkiego przełącznika
Nazwa | Format | Opis |
---|---|---|
ident | ushort = 0x0200 | identyfikowanie pseudokodu operacji |
rozmiar | skrócić | ilość wpisów w tabeli |
Klucze | int[] | lista wartości kluczy size , posortowana od najniższej do najwyższej |
cele | int[] | lista celów gałęzi względnych size , z których każdy odpowiada wartości klucza w tym samym indeksie. Cele odnoszą się do adresu kodu operacji przełącznika, a nie do tej tabeli. |
Uwaga: Całkowita liczba jednostek kodu dla instancji tej tabeli wynosi (size * 4) + 2
.
format wypełnienia-tablicy-danych-ładunek
Nazwa | Format | Opis |
---|---|---|
ident | ushort = 0x0300 | identyfikowanie pseudokodu operacji |
szerokość_elementu | skrócić | liczba bajtów w każdym elemencie |
rozmiar | uint | ilość elementów w tabeli |
dane | ubajt[] | wartości danych |
Uwaga: Całkowita liczba jednostek kodu dla instancji tej tabeli wynosi (size * element_width + 1) / 2 + 4
.
Szczegóły operacji matematycznej
Uwaga: Operacje zmiennoprzecinkowe muszą być zgodne z regułami IEEE 754, stosując zaokrąglanie do najbliższego i stopniowe niedopełnienie, chyba że określono inaczej.
Kod operacji | Semantyka C | Notatki |
---|---|---|
neg-int | int32 a; int32 wynik = -a; | Jednoargumentowe uzupełnienie do dwójek. |
nie-wew | int32 a; wynik int32 = ~a; | Jednoargumentowe uzupełnienie. |
neg-długi | int64 a; int64 wynik = -a; | Jednoargumentowe uzupełnienie do dwójek. |
nie długo | int64 a; int64 wynik = ~a; | Jednoargumentowe uzupełnienie. |
neg-float | pływać; wynik zmiennoprzecinkowy = -a; | Negacja zmiennoprzecinkowa. |
neg-podwójne | podwójne A; podwójny wynik = -a; | Negacja zmiennoprzecinkowa. |
za długi | int32 a; int64 wynik = (int64) a; | Rozszerzenie znaku int32 na int64 . |
Int-to-Float | int32 a; float wynik = (float) a; | Konwersja int32 na float , przy użyciu obrońcy na jeden. Traci to precyzję niektórych wartości. |
Int-to-Double | int32 a; podwójny wynik = (podwójny) a; | Konwersja int32 na double . |
Długo do instalu | int64 a; int32 wynik = (int32) a; | Obcięcie int64 do int32 . |
Długo-płodzący | int64 a; float wynik = (float) a; | Konwersja int64 na float , przy użyciu obrońcy na jeden. Traci to precyzję niektórych wartości. |
Długo-podwójny | int64 a; podwójny wynik = (podwójny) a; | Konwersja int64 na double , przy użyciu obrońcy na jeden. Traci to precyzję niektórych wartości. |
float-to-int | float a; int32 wynik = (int32) a; | Konwersja float na int32 , używając okrągłego zero. NaN i -0.0 (zero ujemne) konwertują na liczbę całkowitą 0 . Nieskończoności i wartości ze zbyt dużą wielkością, aby można je było przedstawić na 0x7fffffff lub -0x80000000 w zależności od znaku. |
pływak do długiego | float a; Int64 wynik = (int64) a; | Konwersja float na int64 , za pomocą Round-Toward-Zero. Te same reguły przypadków szczególnych, co w przypadku float-to-int , z tym, że wartości poza zasięgiem są przekonwertowane na 0x7fffffffffffffff lub -0x8000000000000000 w zależności od znaku. |
float to-podwójny | float a; podwójny wynik = (podwójny) a; | Konwersja float na double , zachowując dokładnie wartość. |
podwójne na inst | podwójne A; int32 wynik = (int32) a; | Konwersja double na int32 , przy użyciu Round-Toward-Zero. Te same reguły przypadków szczególnych, co w przypadku float-to-int . |
podwójnie do długiego | podwójne A; Int64 wynik = (int64) a; | Konwersja double na int64 , przy użyciu Round-Toward-Zero. Obowiązują tutaj te same zasady dotyczące szczególnych przypadków, co w przypadku float-to-long . |
podwójne do floszu | podwójne A; float wynik = (float) a; | Konwersja double na float , przy użyciu obrońcy na jeden. Traci to precyzję niektórych wartości. |
int-bajte | int32 a; Int32 wynik = (a << 24) >> 24; | Obcięcie int32 do int8 , podpisz rozszerzenie wyniku. |
Int-to-Char | int32 a; Int32 wynik = a & 0xffff; | Obcięcie int32 do uint16 , bez przedłużenia znaku. |
int-to-short | int32 a; Int32 wynik = (a << 16) >> 16; | Obcięcie int32 do int16 , podpisanie wyniku. |
dodatek | int32 a, b; Int32 wynik = a + b; | Dodatek do komplementu dwójki. |
Podpis | int32 a, b; Int32 wynik = a - b; | Odejmowanie komplementowania dwójki. |
rsub-int | int32 a, b; Int32 wynik = b - a; | Odejmowanie odwrotnego odejmowania dwójki. |
Mul-int | int32 a, b; Int32 wynik = a * b; | Mnożenie dwójki komplementu. |
Div-int | int32 a, b; Int32 wynik = a / b; | Podział na całość, zaokrąglony w kierunku Zero (to znaczy obcięty na liczbę całkowitą). To rzuca ArithmeticException , jeśli b == 0 . |
rem-int | int32 a, b; Int32 wynik = A % B; | Reszta komplementu po podziale. Znak wyniku jest taki sam jak w przypadku a , i jest dokładniej zdefiniowany jako result == a - (a / b) * b . To rzuca ArithmeticException , jeśli b == 0 . |
i Inte | int32 a, b; Int32 wynik = a & b; | Bitwise i. |
lub int | int32 a, b; Int32 wynik = a | B; | Bitwise lub. |
xor-int | int32 a, b; Int32 wynik = a ^ b; | Bitwise Xor. |
shl-int | int32 a, b; Int32 wynik = a << (b & 0x1f); | Bitwise Shift w lewo (z zamaskowanym argumentem). |
shr-int | int32 a, b; Int32 wynik = a >> (b & 0x1f); | Bitwise podpisane w prawo (z zamaskowanym argumentem). |
ushr-int | uint32 a, b; Int32 wynik = a >> (b & 0x1f); | Bitwise Unsigned Shift w prawo (z zamaskowanym argumentem). |
Dodaj długie | int64 a, b; Int64 wynik = a + b; | Dodatek do komplementu dwójki. |
Sub-długi | int64 a, b; Int64 wynik = a - b; | Odejmowanie komplementowania dwójki. |
Mul-Long | int64 a, b; Int64 wynik = a * b; | Mnożenie dwójki komplementu. |
Div-Long | int64 a, b; Int64 wynik = A / B; | Podział na całość, zaokrąglony w kierunku Zero (to znaczy obcięty na liczbę całkowitą). To rzuca ArithmeticException , jeśli b == 0 . |
REM-Long | int64 a, b; Int64 wynik = A % B; | Reszta komplementu po podziale. Znak wyniku jest taki sam jak w przypadku a , i jest dokładniej zdefiniowany jako result == a - (a / b) * b . To rzuca ArithmeticException , jeśli b == 0 . |
i długi | int64 a, b; Int64 wynik = A&B; | Bitwise i. |
lub długie | int64 a, b; Int64 wynik = a | B; | Bitwise lub. |
Xor-Long | int64 a, b; Int64 wynik = a ^ b; | Bitwise Xor. |
SHL-Long | int64 a; int32 b; Int64 wynik = a << (b & 0x3f); | Bitwise Shift w lewo (z zamaskowanym argumentem). |
SHR-Long | int64 a; int32 b; Int64 wynik = A >> (B & 0x3f); | Bitwise podpisane w prawo (z zamaskowanym argumentem). |
USHR-Long | uint64 a; int32 b; Int64 wynik = A >> (B & 0x3f); | Bitwise Unsigned Shift w prawo (z zamaskowanym argumentem). |
Dodaj-float | float a, b; Wynik float = a + b; | Dodatek Punkt zmiennoprzecinkowy. |
sub-float | float a, b; Wynik float = a - b; | Odejmowanie punktu zmiennoprzecinkowego. |
mul-float | float a, b; Wynik float = a * b; | Mnożenie punktu zmiennoprzecinkowego. |
Div-float | float a, b; Wynik float = a / b; | Dywizja zmiennoprzecinkowa. |
Rem-Float | float a, b; Wynik float = a % b; | Pozostała reszta po podziale. Ta funkcja jest inna niż IEEE 754 pozostałe i jest zdefiniowana jako result == a - roundTowardZero(a / b) * b |
Dodaj-podwójne | Double A, B; Podwójny wynik = a + b; | Dodatek Punkt zmiennoprzecinkowy. |
podwójne | Double A, B; Podwójny wynik = a - b; | Odejmowanie punktu zmiennoprzecinkowego. |
MUL-podwójne | Double A, B; Wynik podwójny = a * b; | Mnożenie punktu zmiennoprzecinkowego. |
Div-Double | Double A, B; Wynik podwójny = A / B; | Dywizja zmiennoprzecinkowa. |
REM-podwójny | Double A, B; Podwójny wynik = A % B; | Pozostała reszta po podziale. Ta funkcja jest inna niż IEEE 754 pozostałe i jest zdefiniowana jako result == a - roundTowardZero(a / b) * b |