Dalvik 字節碼格式

整體設計

  • 機器模型和呼叫約定旨在近似模仿常見的真實架構和 C 風格的呼叫約定:
    • 該機器是基於寄存器的,並且幀在創建時尺寸是固定的。每個幀由特定數量的暫存器(由方法指定)以及執行該方法所需的任何附加資料組成,例如(但不限於)程式計數器和對包含該方法的.dex檔案的引用。
    • 當用於位元值(例如整數和浮點數)時,暫存器被視為 32 位元寬。相鄰暫存器對用於 64 位元值。寄存器對沒有對齊要求。
    • 當用於物件引用時,暫存器被認為足夠寬以恰好容納一個這樣的引用。
    • 從位元表示的角度來看, (Object) null == (int) 0
    • 方法的N 個參數依序存放在方法呼叫訊框的最後N 個暫存器。寬參數消耗兩個暫存器。實例方法傳遞this引用作為其第一個參數。
  • 指令流中的儲存單元是一個16位元無符號數。某些指令中的某些位元被忽略/必須為零。
  • 指令並非無緣無故限制於特定類型。例如,無需解釋即可移動 32 位元暫存器值的指令不必指定它們是移動整數還是浮點數。
  • 對於字串、類型、欄位和方法的引用,有單獨的枚舉和索引常數池。
  • 按位文字資料在指令流中內聯表示。
  • 因為在實務上,一種方法需要超過 16 個暫存器的情況並不常見,而且因為需要超過 8 個暫存器的情況相當常見,所以許多指令僅限於尋址前 16 個暫存器。在合理的情況下,指令允許引用最多前 256 個暫存器。此外,某些指令具有允許更大暫存器計數的變體,包括一對可以定址v0v65535範圍內的暫存器的包羅萬象的move指令。如果指令變體不可用於尋址所需的暫存器,則期望暫存器內容從原始暫存器移動到低位元暫存器(在操作之前)和/或從低位結果暫存器移動到高位結果暫存器。註冊(操作後)。
  • 有幾個「偽指令」用於保存可變長度資料有效負載,它們由常規指令引用(例如fill-array-data )。在正常執行流程中絕對不能遇到此類指令。此外,指令必須位於偶數位節碼偏移量上(即 4 位元組對齊)。為了滿足此要求,dex 產生工具必須發出額外的nop指令作為間隔符號(如果此類指令未對齊)。最後,儘管不是必需的,但預計大多數工具將選擇在方法末尾發出這些指令,因為否則可能會出現需要額外的指令來圍繞它們進行分支的情況。
  • 當安裝在正在運行的系統上時,一些指令可能會被更改,改變它們的格式,作為安裝時靜態連結最佳化。這是為了在已知連結後可以更快地執行。請參閱相關的指令格式文件以了解建議的變體。 「建議」一詞是經過深思熟慮後使用的;實施這些並不是強制性的。
  • 人類語法和助記符:
    • 參數的先到後源排序。
    • 一些操作碼具有消除歧義的名稱後綴來指示它們操作的類型:
      • 通用類型 32 位元操作碼未標記。
      • 通用類型 64 位元操作碼帶有-wide後綴。
      • 特定於類型的操作碼以其類型(或簡單的縮寫)為後綴,為以下之一: -boolean -byte -char -short -int -long -float -double -object -string -class -void
    • 有些操作碼具有消除歧義的後綴,以區分具有不同指令佈局或選項的其他相同操作。這些後綴與主名稱之間用斜杠(“ / ”)分隔,主要是為了在生成和解釋可執行檔的程式碼中與靜態常數進行一對一映射(即減少歧義)對於人類)。
    • 在這裡的描述中,透過每四位寬度使用一個字元來強調值的寬度(指示例如常數的範圍或可能尋址的暫存器的數量)。
    • 例如,在指令「 move-wide/from16 vAA, vBBBB 」:
      • move 」是基本操作碼,表示基本操作(移動暫存器的值)。
      • wide 」是名稱後綴,表示它對寬(64 位元)資料進行操作。
      • from16 」是操作碼後綴,表示以 16 位元暫存器引用作為來源的變體。
      • vAA 」 是目標暫存器(由操作隱含;同樣,規則是目標參數永遠先出現),它必須在v0v255範圍內。
      • vBBBB 」是來源暫存器,它必須在v0v65535範圍內。
  • 有關各種指令格式(在“操作和格式”下列出)的更多詳細信息以及有關操作碼語法的詳細信息,請參閱指令格式文檔
  • 有關字節碼在更大範圍內的位置的更多詳細信息,請參閱.dex文件格式文檔

字節碼集總結

操作與格式助記符/文法論點描述
00 10x廢物循環。

注意:承載資料的偽指令以該操作碼標記,在這種情況下,操作碼單元的高位元組指示資料的性質。請參閱下方的「 packed-switch-payload Format」、「 sparse-switch-payload Format」和「 fill-array-data-payload Format」。

01 12x移動 vA, vB A:目標暫存器(4位元)
B:來源暫存器(4位)
將一個非物件暫存器的內容移到另一個非物件暫存器。
02 22x移動/來自16 vAA, vBBBB A:目標暫存器(8 位元)
B:來源暫存器(16位元)
將一個非物件暫存器的內容移到另一個非物件暫存器。
03 32x移動/16 vAAAA, vBBBB A:目標暫存器(16 位元)
B:來源暫存器(16位元)
將一個非物件暫存器的內容移到另一個非物件暫存器。
04 12x移動範圍 vA, vB A:目標暫存器對(4 位元)
B:來源暫存器對(4位)
將一個寄存器對的內容移至另一對。

注意:v N移動到v N-1v N+1是合法的,因此實作必須安排在寫入任何內容之前讀取暫存器對的兩半。

05 22x移動範圍/from16 vAA, vBBBB A:目標暫存器對(8 位元)
B:來源暫存器對(16位元)
將一個寄存器對的內容移至另一對。

注意:實施注意事項與上面的move-wide相同。

06 32x移動範圍/16 vAAAA、vBBBB A:目標暫存器對(16 位元)
B:來源暫存器對(16位元)
將一個寄存器對的內容移至另一對。

注意:實施注意事項與上面的move-wide相同。

07 12x移動物件 vA, vB A:目標暫存器(4位元)
B:來源暫存器(4位)
將一個物件承載暫存器的內容移到另一個。
08 22x移動物件/from16 vAA、vBBBB A:目標暫存器(8 位元)
B:來源暫存器(16位元)
將一個物件承載暫存器的內容移到另一個。
09 32x移動物件/16 vAAAA、vBBBB A:目標暫存器(16位元)
B:來源暫存器(16位元)
將一個物件承載暫存器的內容移到另一個。
0a 11x移動結果 vAA A:目標暫存器(8 位元)將最近invoke- kind的單字非物件結果移到指定的暫存器。這必須作為緊接在其(單字、非物件)結果不可被忽略的invoke- kind之後的指令來完成;其他地方均無效。
0b 11x移動結果範圍內的 vAA A:目標暫存器對(8 位元)將最近invoke- kind的雙字結果移至指定的暫存器對中。這必須作為緊接在其(雙字)結果不可被忽略的invoke- kind之後的指令來完成;其他地方均無效。
0c 11x移動結果對象 vAA A:目標暫存器(8 位元)將最近invoke- kind的物件結果移動到指定的暫存器。這必須作為緊接在invoke- kindfilled-new-array之後的指令來完成,其(物件)結果不可被忽略;其他地方均無效。
0d 11x移動異常 vAA A:目標暫存器(8 位元)將剛剛捕獲的異常保存到給定的暫存器中。這必須是任何捕獲到的異常不會被忽略的異常處理程序的第一條指令,並且該指令只能作為異常處理程序的第一條指令出現;其他地方均無效。
0e 10x回傳無效void方法返回。
0f 11x返回vAA A:傳回值暫存器(8位元)從單寬度(32 位元)非物件值傳回方法傳回。
10 11x返回範圍的 vAA A:傳回值暫存器對(8 位元)從雙寬度(64 位元)值返回方法返回。
11 11x回傳對象 vAA A:傳回值暫存器(8位元)從物件返回方法返回。
12 11n常數/4 vA,#+B A:目標暫存器(4位元)
B:有符號整數(4 位元)
將給定的文字值(符號擴展為 32 位元)移至指定的暫存器中。
13 21 秒常數/16 vAA,#+BBBB A:目標暫存器(8 位元)
B:有符號整數(16 位元)
將給定的文字值(符號擴展為 32 位元)移至指定的暫存器中。
14 31i常量 vAA, #+BBBBBBBB A:目標暫存器(8 位元)
B:任32位元常數
將給定的文字值移入指定的暫存器。
15 21 點常量/高16 vAA,#+BBBB0000 A:目標暫存器(8 位元)
B:有符號整數(16 位元)
將給定的文字值(右零擴展為 32 位元)移入指定的暫存器。
16 21 秒常量寬/16 vAA,#+BBBB A:目標暫存器(8 位元)
B:有符號整數(16 位元)
將給定的文字值(符號擴展為 64 位元)移至指定的暫存器對中。
17 31i常量寬/32 vAA,#+BBBBBBBB A:目標暫存器(8 位元)
B:有符號整數(32 位元)
將給定的文字值(符號擴展為 64 位元)移至指定的暫存器對中。
18 51升常數範圍 vAA,#+BBBBBBBBBBBBBBBB A:目標暫存器(8 位元)
B:任雙角(64 位元)常數
將給定的文字值移入指定的暫存器對。
19 21 點常量寬/高16 vAA,#+BBBB000000000000 A:目標暫存器(8 位元)
B:有符號整數(16 位元)
將給定的文字值(右零擴展為 64 位元)移到指定的暫存器對中。
1a 21c常數字串 vAA,字串@BBBB A:目標暫存器(8 位元)
B:字串索引
將給定索引指定的字串的參考移至指定的暫存器。
1b 31c常數字串/巨型 vAA,字串@BBBBBBBB A:目標暫存器(8 位元)
B:字串索引
將給定索引指定的字串的參考移至指定的暫存器。
1c 21c常量類 vAA,類型@BBBB A:目標暫存器(8 位元)
B:類型索引
將給定索引指定的類別的參考移至指定的暫存器。在指示的類型是原始類型的情況下,這將儲存對原始類型的簡併類別的參考。
1d 11x監控輸入 vAA A:參考承載暫存器(8 位元)取得指定物件的監視器。
1e 11x監控出口 vAA A:參考承載暫存器(8 位元)釋放指定物件的監視器。

注意:如果該指令需要拋出異常,則必須像 PC 已經超越該指令一樣進行操作。將其視為指令成功執行(在某種意義上),並且在該指令之後但在下一條指令有機會運行之前拋出異常可能會很有用。此定義使得方法可以使用監視器清理包羅萬象(例如, finally )區塊作為該區塊本身的監視器清理,作為處理由於Thread.stop() ,同時仍然設法保持適當的監視器衛生。

1f 21c檢查投射 vAA,輸入@BBBB A:參考承載暫存器(8 位元)
B:類型索引(16位元)
如果給定暫存器中的參考無法轉換為指示的類型,則拋出ClassCastException

注意:由於A必須始終是引用(而不是原始值),因此如果B引用原始類型,則在運行時必然會失敗(即,它將引發異常)。

20 22c vA、vB 的實例,類型@CCCC A:目標暫存器(4位元)
B:參考承載暫存器(4 位元)
C:類型索引(16位元)
如果指示的參考是給定類型的實例,則在給定的目標暫存器中儲存1 ,否則儲存0

注意:由於B必須始終是引用(而不是原始值),因此如果C引用原始類型,則始終會導致儲存0

21 12x數組長度 vA, vB A:目標暫存器(4位元)
B:數組引用暫存器(4 位元)
在給定的目標暫存器中儲存指定數組的長度(以條目為單位)
22 21c新實例 vAA,類型@BBBB A:目標暫存器(8 位元)
B:類型索引
建構指定類型的新實例,並將對其的參考儲存在目標中。該型別必須引用非數組類別。
23 22c新數組 vA、vB、類型@CCCC A:目標暫存器(4位元)
B:尺寸寄存器
C:類型索引
建構一個指定型別和大小的新陣列。該類型必須是數組類型。
24 35c填入新數組 {vC, vD, vE, vF, vG}, type@BBBB A:陣列大小和參數字數(4 位元)
B:類型索引(16位元)
C..G:參數暫存器(每個 4 位元)
建構一個給定類型和大小的數組,並用提供的內容填充它。該類型必須是數組類型。數組的內容必須是單字(即,不能是longdouble數組,但可以接受引用類型)。建構的實例以與方法呼叫指令儲存其結果相同的方式儲存為“結果”,因此必須使用緊接著的move-result-object指令將建構的實例移到暫存器(如果要使用它) )。
25 3rc填入新數組/範圍 {vCCCC .. vNNNN},類型@BBBB A:陣列大小和參數字數(8 位元)
B:類型索引(16位元)
C:第一個參數暫存器(16 位元)
N = A + C - 1
建構一個給定類型和大小的數組,並用提供的內容填充它。說明和限制與上述的filled-new-array相同。
26 31噸fill-array-data vAA,+BBBBBBBB (具有下方「 fill-array-data-payload格式」中指定的補充資料) A:陣列引用(8位元)
B:表資料偽指令的有符號「分支」偏移量(32 位元)
用指定的資料填入給定的陣列。該引用必須是對基元數組的引用,並且資料表必須在類型上與其匹配,並且包含的元素不多於數組所能容納的元素。也就是說,陣列可能比表大,如果是這樣,則僅設定陣列的初始元素,而保留其餘元素。
27 11x投擲vAA A:異常承載暫存器(8位元)
拋出指定的例外。
28 10噸前往+AA A:有符號分支偏移量(8 位元)無條件跳到指定指令。

注意:分支偏移量不能為0 。 (可以使用goto/32或透過在分支之前包含nop作為目標來合法地建構自旋循環。)

29 20噸轉到/16 +AAAA A:有符號分支偏移量(16 位元)
無條件跳到指定指令。

注意:分支偏移量不能為0 。 (可以使用goto/32或透過在分支之前包含nop作為目標來合法地建構自旋循環。)

2a 30t轉到/32 +AAAAAAAA A:有符號分支偏移量(32 位元)
無條件跳到指定指令。
2b 31t Packed-switch vAA、+BBBBBBBB (具有以下「 packed-switch-payload格式」中指定的補充資料) A:註冊測試
B:表資料偽指令的有符號「分支」偏移量(32 位元)
使用與特定整數範圍內的每個值相對應的偏移量表,根據給定暫存器中的值跳到新指令,或者如果不匹配則跳到下一指令。
2c 31t稀疏開關 vAA,+BBBBBBBB (具有下面“ sparse-switch-payload格式”中指定的補充資料) A:註冊測試
B:表資料偽指令的有符號「分支」偏移量(32 位元)
使用值偏移對的有序表,根據給定暫存器中的值跳到新指令,如果沒有匹配,則跳到下一指令。
2d..31 23x cmp類型vAA、vBB、vCC
2d:cmpl-float (lt 偏差)
2e:cmpg-float (gt 偏差)
2f:cmpl-double (lt 偏差)
30:cmpg-double (gt 偏差)
31: cmp 長
A:目標暫存器(8 位元)
B:第一個來源暫存器或對
C:第二個來源暫存器或對
執行指示的浮點或long比較,如果b == ca設為0 ,如果b > c ,則設為1 ,如果b < c ,則設定-1 。為浮點運算所列出的「bias」指示如何處理NaN比較:對於NaN比較,「gtbias」指令傳回1 ,而「ltbias」指令傳回-1

例如,要檢查浮點數是否x < y建議使用cmpg-float ;結果為-1表示測試為 true,其他值表示測試為 false,因為比較有效或其中一個值為NaN

32..37 22噸if-測試vA、vB、+CCCC
32:如果-eq
33:如果-不
34:如果-lt
35:如果-ge
36:如果-gt
37:如果-le
A:第一個要測試的暫存器(4位元)
B:要測試的第二個暫存器(4 位元)
C:有符號分支偏移量(16 位元)
如果給定的兩個暫存器的值按指定進行比較,則轉移到給定的目標。

注意:分支偏移量不能為0 。 (可以透過圍繞向後goto進行分支或透過在分支之前包含nop作為目標來合法地建構自旋循環。)

38..3d 21t if-測試z vAA, +BBBB
38:if-eqz
39:如果-鼻
3a:如果-ltz
3b:if-gez
3c:if-gtz
3d:如果-lez
A:要測試的暫存器(8位元)
B:有符號分支偏移量(16 位元)
如果給定暫存器的值與指定的 0 進行比較,則轉移到給定目標。

注意:分支偏移量不能為0 。 (可以透過圍繞向後goto進行分支或透過在分支之前包含nop作為目標來合法地建構自旋循環。)

3e..43 10x (沒用過) (沒用過)
44..51 23x arrayop vAA、vBB、vCC
44:阿傑
45:全年齡段
46:aget對象
47:aget布林值
48: 取得位元組
49:aget-char
4a:年齡短
4b: aput
4c:aput範圍
4d: aput-對象
4e:aput-布林值
4f: aput 位元組
50: aput 字符
51:aput-short
A:值暫存器或值對;可以是來源或目標(8 位元)
B:數組暫存器(8位)
C:變址暫存器(8位元)
在給定數組的已識別索引處執行已識別數組操作,載入或儲存到值暫存器中。
52..5f 22c i實例操作vA、vB、field@CCCC
52:我得到
53:全iget
54: iget 對象
55: iget布林值
56: iget 字節
57: iget 字符
58:iget-短
59:輸入
5a:輸入範圍
5b:輸入對象
5c:輸入布林值
5d:輸入位元組
5e: 輸入字符
5f:輸入短路
A:值暫存器或值對;可以是來源或目標(4 位元)
B:物件暫存器(4位元)
C:實例欄位引用索引(16位元)
對所識別的欄位執行所識別的物件實例欄位操作,載入或儲存到值暫存器中。

注意:這些操作碼是靜態連結的合理候選者,將欄位參數變更為更直接的偏移量。

60..6d 21c s staticop vAA,field@BBBB
60:sget
61:整個群體
62: sget 對象
63:sget布林值
64: sget 字節
65: sget 字符
66:短的
67:吐痰
68:全範圍
69:sput對象
6a:sput-布林值
6b:輸出位元組
6c:sput-char
6d:濺鍍短路
A:值暫存器或值對;可以是來源或目標(8 位元)
B:靜態欄位引用索引(16位元)
對所識別的靜態欄位執行所識別的物件靜態欄位操作,載入或儲存到值暫存器中。

注意:這些操作碼是靜態連結的合理候選者,將欄位參數變更為更直接的偏移量。

6e..72 35c呼叫類型{vC, vD, vE, vF, vG}, meth@BBBB
6e:呼叫虛擬
6f:呼叫超級
70:直接調用
71:調用靜態
72:呼叫接口
A:參數字數(4 位元)
B:方法參考索引(16位元)
C..G:參數暫存器(每個 4 位元)
呼叫指定的方法。結果(如果有)可以與適當的move-result*變體一起儲存作為緊接著的後續指令。

invoke-virtual用來呼叫普通的虛擬方法(不是privatestaticfinal方法,也不是建構子)。

method_id引用非介面類別的方法時, invoke-super用於呼叫最接近的超類別的虛擬方法(而不是呼叫類別中具有相同method_id的虛擬方法)。對於invoke-virtual也存在相同的方法限制。

在 Dex 檔案版本037或更高版本中,如果method_id引用介面方法, invoke-super用於呼叫該介面上定義的該方法的最具體的、非重寫的版本。對於invoke-virtual也存在相同的方法限制。在版本037之前的 Dex 檔案中,具有介面method_id是非法且未定義的。

invoke-direct用於呼叫非static直接方法(即本質上不可重寫的實例方法,即private實例方法或建構子)。

invoke-static用於呼叫static方法(始終被視為直接方法)。

invoke-interface用於呼叫interface方法,即使用引用interface method_id來呼叫具體類別未知的物件。

注意:這些操作碼是靜態連結的合理候選者,將方法參數變更為更直接的偏移量(或其對)。

73 10x (沒用過) (沒用過)
74..78 3rc調用-種類/範圍{vCCCC .. vNNNN},meth@BBBB
74:呼叫虛擬/範圍
75:呼叫超級/範圍
76:調用直接/範圍
77:調用靜態/範圍
78:呼叫介面/範圍
A:參數字數(8 位元)
B:方法參考索引(16位元)
C:第一個參數暫存器(16 位元)
N = A + C - 1
呼叫指定的方法。有關詳細資訊、注意事項和建議,請參閱上面的第一個invoke- kind描述。
79..7a 10x (沒用過) (沒用過)
7b..8f 12x UNOP vA, vB
7b:負整型
7c:非整數
7d:負長
7e:不長
7f:負浮點數
80:負雙
81:整數到長整型
82:整數到浮點
83:整數到雙精度
84:長整型
85:長期漂浮
86:長到雙倍
87:浮點數轉整數
88:浮動到長
89:浮動到雙精度
8a:雙精度型到整數型
8b:雙倍到長整型
8c:雙浮點
8d:整數到位元組
8e:int 到 char
8f:整數到短
A:目標暫存器或對(4 位元)
B:來源暫存器或對(4 位元)
對來源暫存器執行識別的一元運算,將結果儲存在目標暫存器中。
90..af 23x比諾普vAA、vBB、vCC
90:添加
91:子整數
92: 多整數
93:div-int
94:rem-int
95:和-整數
96: 或-int
97: 異或整數
98:shl-int
99:shr-int
9a:ushr-int
9b:加長
9c:亞長
9d:穆隆
9e:div-長
9f:雷姆-長
a0: 和-長
a1: 或長
a2:異或長
a3: shl-長
a4: shr-長
a5: ushr-長
a6:新增浮動
a7:子浮點
a8:乘法浮點數
a9: div 浮點
aa: rem 浮點
ab:加倍
ac:亞雙
ad:乘法
ae: div-雙精度
af: rem-雙
A:目標暫存器或對(8 位元)
B:第一個來源暫存器或對(8 位元)
C:第二個來源暫存器或對(8 位元)
對兩個來源暫存器執行識別的二進位運算,將結果儲存到目標暫存器中。

注意:與其他-long數學運算(其第一個和第二個來源都採用暫存器對)相反, shl-longshr-longushr-long為其第一個來源採用暫存器對(要移位的值) ),但其第二個來源(移位距離)只有一個暫存器。

b0..cf 12x binop /2addr vA, vB
b0:add-int/2addr
b1: 子整數/2addr
b2: mul-int/2addr
b3: div-int/2addr
b4: rem-int/2addr
b5:and-int/2addr
b6: 或-int/2addr
b7: 異或整數/2addr
b8: shl-int/2addr
b9: shr-int/2addr
ba: ushr-int/2addr
bb:add-long/2addr
bc: 子長/2addr
bd: mul-long/2addr
為:div-long/2addr
bf: rem-long/2addr
c0: and-long/2addr
c1: 或-long/2addr
c2: 異或長/2addr
c3: shl-長/2addr
c4: shr-long/2addr
c5: ushr-long/2addr
c6: 新增浮點/2addr
c7: 子浮點/2addr
c8: mul-float/2addr
c9: div-float/2addr
ca: rem-float/2addr
cb:add-double/2addr
抄送:子雙精度/2addr
cd: 乘法雙精確度/2addr
ce:div-double/2addr
cf: rem-double/2addr
A:目標和第一個來源暫存器或對(4 位元)
B:第二個來源暫存器或對(4 位元)
對兩個來源暫存器執行識別的二進位運算,將結果儲存在第一個來源暫存器中。

注意:與其他-long/2addr數學運算(其目的地/第一個來源和第二個來源都採用暫存器對)相反, shl-long/2addrshr-long/2addrushr-long/2addr採用暫存器對用於其目的地/第一個來源(要移位的值),但單一暫存器用於其第二個來源(移位距離)。

d0..d7 22秒binop /lit16 vA、vB、#+CCCC
d0: 新增 int/lit16
d1:rsub-int(反向減法)
d2: mul-int/lit16
d3:div-int/lit16
d4: rem-int/lit16
d5:and-int/lit16
d6: 或-int/lit16
d7: 異或整數/lit16
A:目標暫存器(4位元)
B:來源暫存器(4位)
C:有符號整數常數(16 位元)
對指定暫存器(第一個參數)和文字值(第二個參數)執行指定的二進位操作,將結果儲存在目標暫存器中。

注意: rsub-int沒有後綴,因為該版本是其係列的主要操作碼。另外,有關其語義的詳細信息,請參閱下文。

d8..e2 22b binop /lit8 vAA、vBB、#+CC
d8: 新增 int/lit8
d9: rsub-int/lit8
da: mul-int/lit8
db:div-int/lit8
dc: rem-int/lit8
dd: 和-int/lit8
de: or-int/lit8
df: 異或整數/lit8
e0: shl-int/lit8
e1: shr-int/lit8
e2: ushr-int/lit8
A:目標暫存器(8 位元)
B:來源暫存器(8位)
C:有符號整數常數(8 位元)
對指定暫存器(第一個參數)和文字值(第二個參數)執行指定的二進位操作,將結果儲存在目標暫存器中。

注意:有關rsub-int語義的詳細信息,請參閱下文。

e3..f9 10x (沒用過) (沒用過)
發45cc呼叫多態 {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A:參數字數(4 位元)
B:方法參考索引(16位元)
C:接收器(4位元)
D..G:參數暫存器(每個 4 位元)
H:原型參考索引(16位元)
呼叫指定的簽章多型方法。結果(如果有)可以與適當的move-result*變體一起儲存作為緊接著的後續指令。

方法參考必須是簽章多型方法,例如java.lang.invoke.MethodHandle.invokejava.lang.invoke.MethodHandle.invokeExact

接收者必須是支援所呼叫的簽章多型方法的物件。

原型參考描述了提供的參數類型和預期的返回類型。

invoke-polymorphic字節碼在執行時可能會引發異常。 API 文件中描述了所呼叫的簽章多型方法的異常情況。

從版本038開始出現在 Dex 檔案中。
FB 4RCC呼叫多態性/範圍 {vCCCC .. vNNNN},meth@BBBB,proto@HHHH A:參數字數(8 位元)
B:方法參考索引(16位元)
C:接收器(16位元)
H:原型參考索引(16位元)
N = A + C - 1
呼叫指定的方法句柄。有關詳細信息,請參閱上面的invoke-polymorphic描述。

從版本038開始出現在 Dex 檔案中。
FC 35c呼叫自訂 {vC、vD、vE、vF、vG},call_site@BBBB A:參數字數(4 位元)
B:呼叫站點參考索引(16 位元)
C..G:參數暫存器(每個 4 位元)
解析並呼叫指定的呼叫站點。呼叫的結果(如果有)可以與適當的move-result*變體一起儲存作為緊接著的後續指令。

此指令分兩個階段執行:呼叫網站解析和呼叫網站呼叫。

呼叫站點解析檢查指示的呼叫站點是否具有關聯的java.lang.invoke.CallSite實例。如果沒有,則使用 DEX 檔案中存在的參數呼叫指定呼叫網站的引導連結器方法(請參閱call_site_item )。引導連結器方法傳回一個java.lang.invoke.CallSite實例,如果不存在關聯,則該實例將與指定的呼叫站點關聯。另一個執行緒可能已經先建立了關聯,如果是這樣,指令的執行將繼續執行第一個關聯的java.lang.invoke.CallSite實例。

呼叫站點呼叫是在已解析的java.lang.invoke.CallSite實例的java.lang.invoke.MethodHandle目標上進行的。呼叫目標就像使用方法句柄和invoke-custom指令的參數作為精確方法句柄呼叫的參數執行invoke-polymorphic (如上所述)一樣。

bootstrap 連結器方法引發的例外狀況包含在java.lang.BootstrapMethodError中。如果出現以下情況,也會引發BootstrapMethodError
  • 引導連結器方法無法傳回java.lang.invoke.CallSite實例。
  • 傳回的java.lang.invoke.CallSite有一個null方法句柄目標。
  • 方法句柄目標不是請求的型別。
從版本038開始出現在 Dex 檔案中。
FD 3RC呼叫自訂/範圍 {vCCCC .. vNNNN},call_site@BBBB A:參數字數(8 位元)
B:呼叫站點參考索引(16位元)
C:第一個參數暫存器(16 位元)
N = A + C - 1
解析並調用調用站點。有關詳細信息,請參閱上面的invoke-custom描述。

從版本038開始出現在 Dex 檔案中。
鐵21c常數方法句柄 vAA,method_handle@BBBB A:目標暫存器(8 位元)
B:方法句柄索引(16位元)
將給定索引指定的方法句柄的參考移至指定的暫存器。

從版本039開始出現在 Dex 檔案中。
FF 21C const 方法類型 vAA,proto@BBBB A:目標暫存器(8 位元)
B:方法原型參考(16位)
將給定索引指定的方法原型的參考移至指定的暫存器。

從版本039開始出現在 Dex 檔案中。

打包交換有效負載格式

姓名格式描述
身分u短= 0x0100辨識偽操作碼
尺寸超短表中的條目數
第一個鍵整數第一個(也是最低的)switch case 值
目標整數[]相對分支目標size的列表。目標與 switch 操作碼的位址相關,而不是與該表的位址相關。

注意:此表的實例的代碼單元總數為(size * 2) + 4

稀疏開關有效負載格式

姓名格式描述
身分u短= 0x0200辨識偽操作碼
尺寸超短表中的條目數
整數[] size鍵值列表,從低到高排序
目標整數[] size相對分支目標的列表,每個目標對應於同一索引處的鍵值。目標與 switch 操作碼的位址相關,而不是與該表的位址相關。

注意:此表的實例的代碼單元總數為(size * 4) + 2

填入數組資料有效負載格式

姓名格式描述
身分短整型 = 0x0300辨識偽操作碼
元素寬度超短每個元素的位元組數
尺寸單位表中的元素數量
數據優字節[]數據值

注意:此表的實例的代碼單元總數為(size * element_width + 1) / 2 + 4

數學運算細節

注意:除非另有說明,浮點運算必須遵循 IEEE 754 規則,使用舍入到最近值和漸進下溢。

操作碼C語意筆記
負整型int32a;
int32 結果 = -a;
一元補碼。
非整數int32a;
int32 結果 = ~a;
一元補碼。
負長int64 一個;
int64 結果 = -a;
一元補碼。
不久int64 一個;
int64 結果 = ~a;
一元補碼。
負浮動浮動一個;
浮點結果=-a;
浮點求反。
負雙雙a;
雙結果=-a;
浮點求反。
整數到長型int32a;
int64 結果 = (int64) a;
int32的擴充簽到int64
int-to-loplat int32 a;
float結果=(float)a;
使用圓頭到達的最新轉換int32float 。對於某些值,這將失去精度。
int to-to-double int32 a;
雙重結果=(double)a;
int32轉換為double
遠處int64 a;
int32結果=(int32)a;
int64將其截斷為int32
長期流動int64 a;
float結果=(float)a;
使用圓頭到達的最新轉換int64float 。對於某些值,這將失去精度。
長到雙int64 a;
雙重結果=(double)a;
使用圓頭到達的最終轉換int64 double 。對於某些值,這將失去精度。
浮動到印度浮動a;
int32結果=(int32)a;
使用圓形 - toward-Zero將float轉換為int32NaN-0.0 (負零)轉換為整數0 。根據符號的不同-0x80000000 0x7fffffff和值太大而無法代表代表。
浮動到長浮動a;
int64結果=(int64)a;
使用圓形toward-Zero將float轉換為int64 。與float-to-int相同的特殊情況規則在此處應用,除了範圍外值轉換為0x7fffffffffffffff-0x8000000000000000 ,具體取決於簽名。
浮動對雙浮動a;
雙重結果=(double)a;
float轉換為double ,準確保留值。
雙到in雙a;
int32結果=(int32)a;
使用圓形零件零,將double轉換為int32 。與float-to-int相同的特殊案例規則在此適用。
雙到長雙a;
int64結果=(int64)a;
使用圓形零件零,將double轉換為int64 。與float-to-long相同的特殊案例規則在此適用。
雙流動性雙a;
float結果=(float)a;
使用double到達的最終轉換為float 。對於某些值,這將失去精度。
int to byte int32 a;
int32結果=(a << 24)>> 24;
int32int8的截斷,簽名以擴展結果。
int-to-char int32 a;
int32結果= a&0xffff;
int32截斷至uint16 ,無符號擴充。
int int32 a;
int32結果=(a << 16)>> 16;
int32int16的截斷,符號擴展結果。
添加int32 a,b;
int32結果= a + b;
二十套添加。
sub-Int int32 a,b;
int32結果= a -b;
兩次匯總減法。
rsub-in int32 a,b;
int32結果= b -a;
兩次彙編反向減法。
mul-int int32 a,b;
int32結果= a * b;
二十二個組合乘法。
Div-Int int32 a,b;
int32結果= a / b;
兩次組合的劃分,朝零(即,被截斷為整數)。如果b == 0 ,這將引發ArithmeticException
rem-Int int32 a,b;
int32結果= a%b;
劃分後的剩餘剩餘時間。結果的符號與a的符號相同,並且更精確地定義為result == a - (a / b) * b 。如果b == 0 ,這將引發ArithmeticException
和int int32 a,b;
INT32結果= A&B;
鑽頭和。
或者int32 a,b;
int32結果= a | b;
鑽頭或。
XOR-INT int32 a,b;
int32結果= a ^ b;
位元XOR。
shl-int int32 a,b;
int32結果= a <<(b&0x1f);
左側移動(有蒙版的參數)。
shr-Int int32 a,b;
int32結果= a >>(b&0x1f);
位元簽名的偏移右(帶有蒙版參數)。
USHR-INT uint32 a,b;
int32結果= a >>(b&0x1f);
位於無符號移動右(帶有蒙版參數)。
加長int64 a,b;
int64結果= a + b;
二十套添加。
int64 a,b;
int64結果= a -b;
兩次匯總減法。
mul-long int64 a,b;
int64結果= a * b;
二十二個組合乘法。
Div-long int64 a,b;
int64結果= a / b;
兩次組合的劃分,朝零(即,被截斷為整數)。如果b == 0 ,這將引發ArithmeticException
雷長int64 a,b;
int64結果= a%b;
劃分後的剩餘剩餘時間。結果的符號與a的符號相同,並且更精確地定義為result == a - (a / b) * b 。如果b == 0 ,這將引發ArithmeticException
int64 a,b;
INT64結果= A&B;
鑽頭和。
int64 a,b;
int64結果= a | b;
鑽頭或。
xor-long int64 a,b;
int64結果= a ^ b;
位元XOR。
shl-long int64 a;
int32 b;
int64結果= a <<(b&0x3f);
左側移動(有蒙版的參數)。
Shr-long int64 a;
int32 b;
int64結果= a >>(b&0x3f);
位元簽名的偏移右(帶有蒙版參數)。
USHR-LONG uint64 a;
int32 b;
int64結果= a >>(b&0x3f);
位於無符號移動右(帶有蒙版參數)。
添加流動float a,b;
浮點結果= a + b;
浮點增加。
子浮動float a,b;
浮點結果= a -b;
浮點減法。
mul-loat float a,b;
浮點結果= a * b;
浮點乘法。
div-loat float a,b;
浮點結果= a / b;
浮點部門。
REM浮動float a,b;
浮點結果= a%b;
劃分後剩餘的浮點。此函數與IEEE 754的剩餘不同,並定義為result == a - roundTowardZero(a / b) * b
加雙雙a,b;
雙重結果= a + b;
浮點增加。
子雙雙a,b;
雙重結果= a -b;
浮點減法。
穆爾雙雙a,b;
雙重結果= a * b;
浮點乘法。
Div-double雙a,b;
雙重結果= a / b;
浮點部門。
rem-double雙a,b;
雙重結果= a%b;
劃分後剩餘的浮點。此函數與IEEE 754的剩餘不同,並定義為result == a - roundTowardZero(a / b) * b