Dalvik bytecode

Thiết kế chung

  • Mô hình máy và các quy ước gọi có nghĩa là gần như bắt chước các kiến ​​trúc thực phổ biến và các quy ước gọi kiểu C:
    • Máy dựa trên thanh ghi và các khung có kích thước cố định khi tạo. Mỗi khung bao gồm một số thanh ghi cụ thể (được chỉ định bởi phương thức) cũng như bất kỳ dữ liệu bổ trợ nào cần thiết để thực thi phương thức, chẳng hạn như (nhưng không giới hạn) bộ đếm chương trình và một tham chiếu đến tệp .dex có chứa phương thức .
    • Khi được sử dụng cho các giá trị bit (chẳng hạn như số nguyên và số dấu phẩy động), thanh ghi được coi là rộng 32 bit. Các cặp thanh ghi liền kề được sử dụng cho các giá trị 64 bit. Không có yêu cầu căn chỉnh cho các cặp thanh ghi.
    • Khi được sử dụng cho các tham chiếu đối tượng, thanh ghi được coi là đủ rộng để chứa chính xác một tham chiếu như vậy.
    • Về phương diện biểu diễn theo bit, (Object) null == (int) 0 .
    • N đối số của một phương thức nằm trong N thanh ghi cuối cùng của khung gọi phương thức, theo thứ tự. Đối số rộng sử dụng hai thanh ghi. Các phương thức phiên bản được chuyển một tham chiếu this làm đối số đầu tiên của chúng.
  • Đơn vị lưu trữ trong luồng lệnh là số lượng 16-bit không dấu. Một số bit trong một số lệnh bị bỏ qua / phải bằng không.
  • Hướng dẫn không bị giới hạn một cách vô cớ đối với một loại cụ thể. Ví dụ, các lệnh di chuyển các giá trị thanh ghi 32 bit mà không cần diễn giải không phải chỉ định liệu chúng đang di chuyển int hay float.
  • Có các nhóm hằng số được liệt kê và lập chỉ mục riêng cho các tham chiếu đến chuỗi, kiểu, trường và phương thức.
  • Dữ liệu theo chiều dọc bit được biểu diễn trong dòng trong dòng lệnh.
  • Bởi vì, trong thực tế, một phương thức cần nhiều hơn 16 thanh ghi là không phổ biến và bởi vì việc cần nhiều hơn 8 thanh ghi là điều khá phổ biến, nên nhiều lệnh bị giới hạn ở việc chỉ giải quyết 16 thanh ghi đầu tiên. Khi hợp lý có thể, các hướng dẫn cho phép tham chiếu đến tối đa 256 thanh ghi đầu tiên. Ngoài ra, một số lệnh có các biến thể cho phép số lượng thanh ghi lớn hơn nhiều, bao gồm một cặp lệnh move bắt tất cả có thể giải quyết các thanh ghi trong phạm vi v0 - v65535 . Trong trường hợp một biến thể lệnh không có sẵn để giải quyết một thanh ghi mong muốn, thì nội dung thanh ghi sẽ được chuyển từ thanh ghi ban đầu sang thanh ghi thấp (trước khi hoạt động) và / hoặc chuyển từ thanh ghi kết quả thấp lên cao. đăng ký (sau khi hoạt động).
  • Có một số "lệnh giả" được sử dụng để chứa các trọng tải dữ liệu có độ dài thay đổi, được tham chiếu bởi các lệnh thông thường (ví dụ: fill-array-data ). Không bao giờ được gặp các hướng dẫn như vậy trong quá trình thực thi thông thường. Ngoài ra, các hướng dẫn phải được đặt trên các hiệu số bytecode được đánh số chẵn (nghĩa là, căn chỉnh 4 byte). Để đáp ứng yêu cầu này, các công cụ tạo dex phải phát ra một lệnh nop bổ sung như một bộ đệm nếu lệnh như vậy không được đánh dấu. Cuối cùng, mặc dù không bắt buộc, người ta mong đợi rằng hầu hết các công cụ sẽ chọn phát ra các lệnh này ở cuối các phương thức, vì nếu không sẽ có trường hợp cần các lệnh bổ sung để phân nhánh xung quanh chúng.
  • Khi được cài đặt trên một hệ thống đang chạy, một số hướng dẫn có thể bị thay đổi, thay đổi định dạng của chúng, như một cách tối ưu hóa liên kết tĩnh trong thời gian cài đặt. Điều này cho phép thực thi nhanh hơn khi đã biết liên kết. Xem tài liệu định dạng hướng dẫn liên quan để biết các biến thể được đề xuất. Từ "đề nghị" được sử dụng một cách khuyên nhủ; không bắt buộc phải thực hiện những điều này.
  • Cú pháp con người và ghi nhớ:
    • Thứ tự đích-sau đó-nguồn cho các đối số.
    • Một số mã opcode có hậu tố tên phân biệt để chỉ ra (các) loại mà chúng hoạt động:
      • Loại mã quang 32-bit chung không được đánh dấu.
      • Loại mã quang 64-bit chung được gắn với -wide .
      • Các mã opcode cụ thể cho loại được ghi kèm theo loại của chúng (hoặc viết tắt đơn giản), một trong số: -boolean -byte -char -short -int -long -float -double -object -string -class -void
    • Một số mã opcodes có hậu tố phân biệt để phân biệt các hoạt động giống hệt nhau có bố cục hoặc tùy chọn hướng dẫn khác nhau. Các hậu tố này được phân tách khỏi tên chính bằng dấu gạch chéo (" / ") và chủ yếu tồn tại để tạo ánh xạ một-một với các hằng số tĩnh trong mã tạo và diễn giải các tệp thực thi (nghĩa là, để giảm sự mơ hồ cho con người).
    • Trong các mô tả ở đây, chiều rộng của một giá trị (ví dụ, cho biết phạm vi của một hằng số hoặc số lượng thanh ghi có thể được giải quyết) được nhấn mạnh bằng cách sử dụng một ký tự trên bốn bit chiều rộng.
    • Ví dụ: trong hướng dẫn " move-wide/from16 vAA, vBBBB ":
      • " move " là opcode cơ sở, cho biết hoạt động cơ sở (di chuyển giá trị của thanh ghi).
      • " wide " là hậu tố tên, cho biết rằng nó hoạt động trên dữ liệu rộng (64 bit).
      • " from16 " là hậu tố opcode, chỉ ra một biến thể có tham chiếu thanh ghi 16 bit làm nguồn.
      • " vAA " là thanh ghi đích (được ngụ ý bởi hoạt động; một lần nữa, quy tắc là các đối số đích luôn đến trước), thanh ghi này phải nằm trong phạm vi v0 - v255 .
      • " vBBBB " là thanh ghi nguồn, phải nằm trong dải v0 - v65535 .
  • Xem tài liệu định dạng hướng dẫn để biết thêm chi tiết về các định dạng hướng dẫn khác nhau (được liệt kê trong "Op & Format") cũng như chi tiết về cú pháp opcode.
  • Xem tài liệu định dạng tệp .dex để biết thêm chi tiết về vị trí của mã bytecode phù hợp với bức tranh lớn hơn.

Tóm tắt bộ mã bytecode

Op & Định dạng Ghi nhớ / Cú pháp Tranh luận Sự mô tả
00 10x nop Các chu trình thải.

Lưu ý: Các lệnh giả mang dữ liệu được gắn thẻ với opcode này, trong trường hợp này byte bậc cao của đơn vị opcode cho biết bản chất của dữ liệu. Xem "Định dạng packed-switch-payload ", "Định dạng sparse-switch-payload " và "Định dạng tải fill-array-data-payload " bên dưới.

01 12x di chuyển vA, vB A: thanh ghi đích (4 bit)
B: thanh ghi nguồn (4 bit)
Di chuyển nội dung của một thanh ghi không phải đối tượng này sang một thanh ghi khác.
02 22x di chuyển / từ 16 vAA, vBBBB A: thanh ghi đích (8 bit)
B: thanh ghi nguồn (16 bit)
Di chuyển nội dung của một thanh ghi không phải đối tượng này sang một thanh ghi khác.
03 32x di chuyển / 16 vAAAA, vBBBB A: thanh ghi đích (16 bit)
B: thanh ghi nguồn (16 bit)
Di chuyển nội dung của một thanh ghi không phải đối tượng này sang một thanh ghi khác.
04 12x di chuyển rộng vA, vB A: cặp thanh ghi đích (4 bit)
B: cặp thanh ghi nguồn (4 bit)
Di chuyển nội dung của cặp thanh ghi này sang cặp thanh ghi khác.

Lưu ý: Việc chuyển từ v N sang v N-1 hoặc v N+1 là hợp pháp, vì vậy việc triển khai phải sắp xếp để cả hai nửa của cặp thanh ghi được đọc trước khi bất kỳ thứ gì được ghi.

05 22x di chuyển rộng / từ 16 vAA, vBBBB A: cặp thanh ghi đích (8 bit)
B: cặp thanh ghi nguồn (16 bit)
Di chuyển nội dung của cặp thanh ghi này sang cặp thanh ghi khác.

Lưu ý: Các cân nhắc triển khai cũng giống như move-wide trên.

06 32x di chuyển rộng / 16 vAAAA, vBBBB A: cặp thanh ghi đích (16 bit)
B: cặp thanh ghi nguồn (16 bit)
Di chuyển nội dung của cặp thanh ghi này sang cặp thanh ghi khác.

Lưu ý: Các cân nhắc triển khai cũng giống như move-wide trên.

07 12x đối tượng di chuyển vA, vB A: thanh ghi đích (4 bit)
B: thanh ghi nguồn (4 bit)
Di chuyển nội dung của một thanh ghi mang đối tượng này sang một thanh ghi mang đối tượng khác.
08 22x move-object / from16 vAA, vBBBB A: thanh ghi đích (8 bit)
B: thanh ghi nguồn (16 bit)
Di chuyển nội dung của một thanh ghi mang đối tượng này sang một thanh ghi mang đối tượng khác.
09 32x move-object / 16 vAAAA, vBBBB A: thanh ghi đích (16 bit)
B: thanh ghi nguồn (16 bit)
Di chuyển nội dung của một thanh ghi mang đối tượng này sang một thanh ghi mang đối tượng khác.
0a 11x kết quả di chuyển vAA A: thanh ghi đích (8 bit) Di chuyển kết quả không phải đối tượng một từ của loại lệnh gọi gần đây invoke- kind vào thanh ghi được chỉ định. Điều này phải được thực hiện dưới dạng lệnh ngay sau một invoke- kind mà kết quả (một từ, không phải đối tượng) không bị bỏ qua; bất kỳ nơi nào khác là không hợp lệ.
0b 11x chuyển-kết quả-rộng vAA A: cặp thanh ghi đích (8 bit) Di chuyển kết quả từ kép của kiểu gọi gần đây invoke- kind vào cặp thanh ghi được chỉ định. Điều này phải được thực hiện dưới dạng lệnh ngay sau một invoke- kind mà kết quả (từ kép) không bị bỏ qua; bất kỳ nơi nào khác là không hợp lệ.
0c 11x move-result-object vAA A: thanh ghi đích (8 bit) Di chuyển kết quả đối tượng của kiểu gọi gần đây invoke- kind vào thanh ghi được chỉ định. Điều này phải được thực hiện dưới dạng lệnh ngay sau một invoke- kind filled-new-array mà kết quả (đối tượng) của nó không bị bỏ qua; bất kỳ nơi nào khác là không hợp lệ.
0ngày 11x di chuyển ngoại lệ vAA A: thanh ghi đích (8 bit) Lưu một ngoại lệ vừa bắt được vào thanh ghi đã cho. Đây phải là lệnh đầu tiên của bất kỳ trình xử lý ngoại lệ nào mà ngoại lệ bắt được không được bỏ qua, và lệnh này chỉ được xuất hiện như là lệnh đầu tiên của trình xử lý ngoại lệ; bất kỳ nơi nào khác là không hợp lệ.
0e 10x trả về vô hiệu Trả về từ một phương thức void .
0f 11x trả lại vAA A: thanh ghi giá trị trả về (8 bit) Trả về từ phương thức trả về giá trị không phải đối tượng một chiều rộng (32 bit).
10 11x trả về toàn bộ vAA A: cặp thanh ghi giá trị trả về (8 bit) Trả về từ phương thức trả về giá trị độ rộng kép (64-bit).
11 11x đối tượng trả về vAA A: thanh ghi giá trị trả về (8 bit) Trả về từ một phương thức trả về đối tượng.
12 11n const / 4 vA, # + B A: thanh ghi đích (4 bit)
B: int có dấu (4 bit)
Di chuyển giá trị chữ đã cho (dấu mở rộng đến 32 bit) vào thanh ghi được chỉ định.
13 giây 21 const / 16 vAA, # + BBBB A: thanh ghi đích (8 bit)
B: int có dấu (16 bit)
Di chuyển giá trị chữ đã cho (dấu mở rộng đến 32 bit) vào thanh ghi được chỉ định.
14 31i const vAA, # + BBBBBBBB A: thanh ghi đích (8 bit)
B: hằng số 32 bit tùy ý
Di chuyển giá trị chữ đã cho vào thanh ghi được chỉ định.
15 21h const / high16 vAA, # + BBBB0000 A: thanh ghi đích (8 bit)
B: int có dấu (16 bit)
Di chuyển giá trị chữ đã cho (phải-không-mở rộng thành 32 bit) vào thanh ghi được chỉ định.
16 21 const-wide / 16 vAA, # + BBBB A: thanh ghi đích (8 bit)
B: int có dấu (16 bit)
Di chuyển giá trị chữ đã cho (dấu mở rộng thành 64 bit) vào cặp thanh ghi được chỉ định.
17 31i const-wide / 32 vAA, # + BBBBBBBB A: thanh ghi đích (8 bit)
B: int có dấu (32 bit)
Di chuyển giá trị chữ đã cho (dấu mở rộng thành 64 bit) vào cặp thanh ghi được chỉ định.
18 51l const-wide vAA, # + BBBBBBBBBBBBBBBB A: thanh ghi đích (8 bit)
B: hằng số độ rộng kép (64-bit) tùy ý
Di chuyển giá trị chữ đã cho vào cặp thanh ghi được chỉ định.
19 21h const-wide / high16 vAA, # + BBBB000000000000 A: thanh ghi đích (8 bit)
B: int có dấu (16 bit)
Di chuyển giá trị chữ đã cho (phải-không-mở rộng thành 64 bit) vào cặp thanh ghi được chỉ định.
1a 21c const-string vAA, string @ BBBB A: thanh ghi đích (8 bit)
B: chỉ số chuỗi
Di chuyển một tham chiếu đến chuỗi được chỉ định bởi chỉ mục đã cho vào thanh ghi được chỉ định.
1b 31c const-string / jumbo vAA, string @ BBBBBBBB A: thanh ghi đích (8 bit)
B: chỉ số chuỗi
Di chuyển một tham chiếu đến chuỗi được chỉ định bởi chỉ mục đã cho vào thanh ghi được chỉ định.
1c 21c const-class vAA, nhập @ BBBB A: thanh ghi đích (8 bit)
B: loại chỉ mục
Di chuyển một tham chiếu đến lớp được chỉ định bởi chỉ mục đã cho vào thanh ghi được chỉ định. Trong trường hợp kiểu được chỉ định là kiểu nguyên thủy, điều này sẽ lưu trữ một tham chiếu đến lớp suy biến của kiểu nguyên thủy.
1ngày 11x monitor-enter vAA A: thanh ghi mang tham chiếu (8 bit) Mua màn hình cho đối tượng được chỉ định.
1e 11x theo dõi-thoát vAA A: thanh ghi mang tham chiếu (8 bit) Nhả màn hình cho đối tượng được chỉ định.

Lưu ý: Nếu lệnh này cần phải ném một ngoại lệ, nó phải làm như vậy nếu máy tính đã nâng cao hơn lệnh. Có thể hữu ích khi nghĩ về điều này khi lệnh thực thi thành công (theo một nghĩa nào đó), và ngoại lệ được ném sau lệnh nhưng trước khi lệnh tiếp theo có cơ hội chạy. Định nghĩa này giúp cho một phương pháp có thể sử dụng khối bắt tất cả (ví dụ: finally ) dọn dẹp màn hình làm khối dọn dẹp màn hình cho chính khối đó, như một cách để xử lý các ngoại lệ tùy ý có thể bị ném do quá trình triển khai trước đây của Thread.stop() , trong khi vẫn quản lý để có vệ sinh màn hình thích hợp.

1f 21c kiểm tra truyền vAA, nhập @ BBBB A: thanh ghi mang tham chiếu (8 bit)
B: loại chỉ mục (16 bit)
Ném một ClassCastException nếu tham chiếu trong thanh ghi đã cho không thể được truyền sang kiểu được chỉ định.

Lưu ý:A phải luôn là một tham chiếu (và không phải là một giá trị nguyên thủy), điều này nhất thiết sẽ không thành công trong thời gian chạy (nghĩa là, nó sẽ ném ra một ngoại lệ) nếu B tham chiếu đến một kiểu nguyên thủy.

20 22c phiên bản của vA, vB, loại @ CCCC A: thanh ghi đích (4 bit)
B: thanh ghi mang tham chiếu (4 bit)
C: loại chỉ mục (16 bit)
Lưu trữ trong thanh ghi đích đã cho 1 nếu tham chiếu được chỉ định là một thể hiện của kiểu đã cho, hoặc 0 nếu không.

Lưu ý:B phải luôn là một tham chiếu (và không phải là một giá trị nguyên thủy), điều này sẽ luôn dẫn đến việc 0 được lưu trữ nếu C tham chiếu đến một kiểu nguyên thủy.

21 12x độ dài mảng vA, vB A: thanh ghi đích (4 bit)
B: thanh ghi mang tham chiếu mảng (4 bit)
Lưu trữ trong thanh ghi đích đã cho độ dài của mảng được chỉ định, trong các mục nhập
22 21c vAA phiên bản mới, nhập @ BBBB A: thanh ghi đích (8 bit)
B: loại chỉ mục
Xây dựng một phiên bản mới của kiểu được chỉ định, lưu trữ một tham chiếu đến nó trong đích. Kiểu phải tham chiếu đến một lớp không phải là mảng.
23 22c mảng mới vA, vB, loại @ CCCC A: thanh ghi đích (4 bit)
B: kích thước đăng ký
C: loại chỉ mục
Xây dựng một mảng mới với kiểu và kích thước được chỉ định. Kiểu phải là kiểu mảng.
24 35c mới-đầy-mảng {vC, vD, vE, vF, vG}, loại @ BBBB A: kích thước mảng và số lượng từ đối số (4 bit)
B: loại chỉ mục (16 bit)
C..G: thanh ghi đối số (mỗi thanh ghi 4 bit)
Xây dựng một mảng có kiểu và kích thước đã cho, điền vào nó với nội dung được cung cấp. Kiểu phải là kiểu mảng. Nội dung của mảng phải là một từ đơn (nghĩa là không có mảng long hoặc double , nhưng các kiểu tham chiếu được chấp nhận). Cá thể đã xây dựng được lưu trữ dưới dạng "kết quả" giống như cách mà các lệnh gọi phương thức lưu trữ kết quả của chúng, do đó, cá thể đã xây dựng phải được chuyển đến một thanh ghi có lệnh move-result-object ngay sau đó (nếu nó được sử dụng ).
25 3rc đầy-mới-mảng / dải ô {vCCCC .. vNNNN}, nhập @ BBBB A: kích thước mảng và số lượng từ đối số (8 bit)
B: loại chỉ mục (16 bit)
C: thanh ghi đối số đầu tiên (16 bit)
N = A + C - 1
Xây dựng một mảng có kiểu và kích thước đã cho, điền vào nó với nội dung được cung cấp. Giải thích và hạn chế cũng giống như filled-new-array , được mô tả ở trên.
26 31t lấp đầy-mảng-dữ liệu vAA, + BBBBBBBB (với dữ liệu bổ sung như được chỉ định bên dưới trong "Định dạng fill-array-data-payload ") A: tham chiếu mảng (8 bit)
B: offset "nhánh" đã ký thành lệnh giả dữ liệu bảng (32 bit)
Điền vào mảng đã cho với dữ liệu được chỉ định. Tham chiếu phải là một mảng nguyên thủy và bảng dữ liệu phải khớp với nó về kiểu và không được chứa nhiều phần tử hơn sẽ phù hợp với mảng. Nghĩa là, mảng có thể lớn hơn bảng và nếu vậy, chỉ các phần tử ban đầu của mảng được thiết lập, để lại phần còn lại.
27 11x ném vAA A: thanh ghi mang ngoại lệ (8 bit)
Ném ngoại lệ được chỉ định.
28 10t goto + AA A: độ lệch nhánh có dấu (8 bit) Chuyển đến hướng dẫn được chỉ định một cách vô điều kiện.

Lưu ý: Độ lệch nhánh không được bằng 0 . (Một vòng quay có thể được xây dựng hợp pháp bằng goto/32 hoặc bằng cách bao gồm một nop làm mục tiêu trước nhánh.)

29 20t goto / 16 + AAAA A: độ lệch nhánh có dấu (16 bit)
Chuyển đến hướng dẫn được chỉ định một cách vô điều kiện.

Lưu ý: Độ lệch nhánh không được bằng 0 . (Một vòng quay có thể được xây dựng hợp pháp bằng goto/32 hoặc bằng cách bao gồm một nop làm mục tiêu trước nhánh.)

2a 30t goto / 32 + AAAAAAAA A: độ lệch nhánh có dấu (32 bit)
Chuyển đến hướng dẫn được chỉ định một cách vô điều kiện.
2b 31t đóng gói-chuyển đổi vAA, + BBBBBBBB (với dữ liệu bổ sung như được chỉ định bên dưới trong "Định dạng packed-switch-payload ") A: đăng ký để kiểm tra
B: offset "nhánh" đã ký thành lệnh giả dữ liệu bảng (32 bit)
Chuyển đến một lệnh mới dựa trên giá trị trong thanh ghi đã cho, sử dụng bảng hiệu số tương ứng với mỗi giá trị trong một phạm vi tích phân cụ thể hoặc chuyển sang lệnh tiếp theo nếu không có kết quả phù hợp.
2c 31t vAA chuyển đổi thưa thớt, + BBBBBBBB (với dữ liệu bổ sung như được chỉ định bên dưới trong "Định dạng sparse-switch-payload chuyển đổi chậm") A: đăng ký để kiểm tra
B: offset "nhánh" đã ký thành lệnh giả dữ liệu bảng (32 bit)
Chuyển đến một lệnh mới dựa trên giá trị trong thanh ghi đã cho, sử dụng một bảng có thứ tự các cặp giá trị-bù trừ hoặc chuyển sang lệnh tiếp theo nếu không có khớp.
2d..31 23x cmp loại vAA, vBB, vCC
2d: cmpl-float (lt bias)
2e: cmpg-float (thiên vị gt)
2f: cmpl-double (lt bias)
30: cmpg-double (gt bias)
31: cmp-long
A: thanh ghi đích (8 bit)
B: thanh ghi nguồn đầu tiên hoặc cặp
C: thanh ghi nguồn thứ hai hoặc cặp
Thực hiện phép so sánh long hoặc dấu phẩy động được chỉ ra, đặt a thành 0 nếu b == c , 1 nếu b > c , hoặc -1 nếu b < c . "Độ lệch" được liệt kê cho các phép toán dấu phẩy động cho biết cách so sánh NaN được xử lý như thế nào: lệnh "gt bias" trả về 1 cho phép so sánh NaN và lệnh "lt bias" trả về -1 .

Ví dụ, để kiểm tra xem dấu phẩy động x < y có nên sử dụng cmpg-float hay không; kết quả -1 cho biết rằng thử nghiệm là đúng và các giá trị khác cho biết là sai do so sánh hợp lệ hoặc vì một trong các giá trị là NaN .

32..37 22t if- kiểm tra vA, vB, + CCCC
32: if-eq
33: if-ne
34: nếu-lt
35: if-ge
36: if-gt
37: if-le
A: đăng ký đầu tiên để kiểm tra (4 bit)
B: thanh ghi thứ hai để kiểm tra (4 bit)
C: độ lệch nhánh có dấu (16 bit)
Nhánh tới đích đã cho nếu giá trị của hai thanh ghi đã cho so sánh như được chỉ định.

Lưu ý: Độ lệch nhánh không được bằng 0 . (Một vòng quay có thể được xây dựng hợp pháp bằng cách phân nhánh xung quanh một goto lùi hoặc bằng cách bao gồm một nop làm mục tiêu trước nhánh.)

38..3d 21t if- kiểm tra z vAA, + BBBB
38: if-eqz
39: if-nez
3a: if-ltz
3b: if-gez
3c: if-gtz
3d: if-lez
A: đăng ký để kiểm tra (8 bit)
B: độ lệch nhánh có dấu (16 bit)
Nhánh tới đích đã cho nếu giá trị của thanh ghi đã cho so sánh với 0 như được chỉ định.

Lưu ý: Độ lệch nhánh không được bằng 0 . (Một vòng quay có thể được xây dựng hợp pháp bằng cách phân nhánh xung quanh một goto lùi hoặc bằng cách bao gồm một nop làm mục tiêu trước nhánh.)

3e..43 10x (không sử dụng) (không sử dụng)
44..51 23x arrayop vAA, vBB, vCC
44: aget
45: aget-wide
46: aget-object
47: aget-boolean
48: aget-byte
49: aget-char
4a: ngắn hạn
4b: aput
4c: rộng rãi
4d: aput-object
4e: aput-boolean
4f: aput-byte
50: aput-char
51: aput-short
A: thanh ghi giá trị hoặc cặp; có thể là nguồn hoặc đích (8 bit)
B: thanh ghi mảng (8 bit)
C: thanh ghi chỉ mục (8 bit)
Thực hiện thao tác mảng đã xác định tại chỉ mục đã xác định của mảng đã cho, tải hoặc lưu trữ vào thanh ghi giá trị.
52..5f 22c tôi instanceop vA, vB, field @ CCCC
52: iget
53: toàn bộ
54: iget-object
55: iget-boolean
56: iget-byte
57: iget-char
58: iget-short
59: iput
5a: iput-wide
5b: iput-object
5c: iput-boolean
5d: iput-byte
5e: iput-char
5f: iput-short
A: thanh ghi giá trị hoặc cặp; có thể là nguồn hoặc đích (4 bit)
B: thanh ghi đối tượng (4 bit)
C: chỉ mục tham chiếu trường cá thể (16 bit)
Thực hiện thao tác trường cá thể đối tượng đã xác định với trường đã xác định, tải hoặc lưu trữ vào thanh ghi giá trị.

Lưu ý: Các mã opcode này là ứng cử viên hợp lý cho liên kết tĩnh, thay đổi đối số trường thành một phần bù trực tiếp hơn.

60..6d 21c s staticop vAA, trường @ BBBB
60: sget
61: rộng rãi
62: sget-object
63: sget-boolean
64: sget-byte
65: sget-char
66: sget-short
67: sput
68: rộng rãi
69: sput-object
6a: sput-boolean
6b: sput-byte
6c: sput-char
6d: sput-short
A: thanh ghi giá trị hoặc cặp; có thể là nguồn hoặc đích (8 bit)
B: chỉ số tham chiếu trường tĩnh (16 bit)
Thực hiện thao tác trường tĩnh đối tượng đã xác định với trường tĩnh đã xác định, tải hoặc lưu trữ vào thanh ghi giá trị.

Lưu ý: Các mã opcode này là ứng cử viên hợp lý cho liên kết tĩnh, thay đổi đối số trường thành một phần bù trực tiếp hơn.

6e..72 35c gọi loại {vC, vD, vE, vF, vG}, meth @ BBBB
6e: gọi-ảo
6f: gọi siêu cấp
70: gọi trực tiếp
71: gọi tĩnh
72: giao diện gọi
A: số từ đối số (4 bit)
B: chỉ số tham chiếu phương thức (16 bit)
C..G: thanh ghi đối số (mỗi thanh ghi 4 bit)
Gọi phương pháp được chỉ định. Kết quả (nếu có) có thể được lưu trữ với một biến thể move-result* thích hợp làm hướng dẫn ngay sau đó.

invoke-virtual được sử dụng để gọi một phương thức ảo bình thường (một phương thức không phải là private , static hoặc final , và cũng không phải là một phương thức khởi tạo).

Khi method_id tham chiếu đến một phương thức của một lớp không phải giao diện, invoke-super được sử dụng để gọi phương thức ảo của lớp cha gần nhất (trái ngược với phương thức có cùng method_id trong lớp đang gọi). Các hạn chế về phương thức giống như đối với invoke-virtual .

Trong tệp Dex phiên bản 037 trở lên, nếu method_id đề cập đến một phương thức giao diện, thì invoke-super được sử dụng để gọi phiên bản cụ thể nhất, không bị ghi đè của phương thức đó được xác định trên giao diện đó. Các hạn chế về phương thức giống như đối với invoke-virtual . Trong các tệp Dex trước phiên bản 037 , có method_id giao diện là bất hợp pháp và không xác định.

invoke-direct được sử dụng để gọi một phương thức trực tiếp không static (nghĩa là một phương thức thể hiện về bản chất của nó là không thể ghi đè, cụ thể là một phương thức private thể riêng hoặc một phương thức khởi tạo).

invoke-static được sử dụng để gọi một phương thức static (luôn được coi là một phương thức trực tiếp).

invoke-interface được sử dụng để gọi một phương thức interface , nghĩa là, trên một đối tượng có lớp cụ thể không được biết đến, bằng cách sử dụng method_id đến một interface .

Lưu ý: Các mã opcode này là ứng cử viên hợp lý cho liên kết tĩnh, thay đổi đối số phương thức thành một phần bù trực tiếp hơn (hoặc cặp của chúng).

73 10x (không sử dụng) (không sử dụng)
74..78 3rc gọi- loại / phạm vi {vCCCC .. vNNNN}, meth @ BBBB
74: gọi-ảo / phạm vi
75: gọi siêu cấp / phạm vi
76: gọi trực tiếp / phạm vi
77: gọi-tĩnh / phạm vi
78: gọi giao diện / phạm vi
A: số từ đối số (8 bit)
B: chỉ số tham chiếu phương thức (16 bit)
C: thanh ghi đối số đầu tiên (16 bit)
N = A + C - 1
Gọi phương pháp được chỉ định. Xem mô tả invoke- kind đầu tiên ở trên để biết chi tiết, cảnh báo và đề xuất.
79..7a 10x (không sử dụng) (không sử dụng)
7b..8f 12x unop vA, vB
7b: neg-int
7c: not-int
7d: neg-long
7e: không lâu
7f: neg-float
80: neg-double
81: int-to-long
82: int-to-float
83: int-to-double
84: long-to-int
85: lâu nổi
86: dài-to-gấp đôi
87: float-to-int
88: float-to-long
89: float-to-double
8a: double-to-int
8b: dài gấp đôi
8c: double-to-float
8d: int-to-byte
8e: int-to-char
8f: int-to-short
A: thanh ghi đích hoặc cặp (4 bit)
B: thanh ghi nguồn hoặc cặp (4 bit)
Thực hiện thao tác đơn nguyên đã xác định trên thanh ghi nguồn, lưu trữ kết quả trong thanh ghi đích.
90..af 23x binop vAA, vBB, vCC
90: add-int
91: int phụ
92: đa int
93: div-int
94: rem-int
95: và-int
96: hoặc-int
97: xor-int
98: shl-int
99: shr-int
9a: ushr-int
9b: thêm dài
9c: tiểu dài
9d: đa dài
9e: div-long
9f: rem-long
a0: and-long
a1: hoặc-dài
a2: xor-long
a3: dài
a4: dài
a5: ushr-long
a6: add-float
a7: sub-float
a8: mul-float
a9: div-float
aa: rem-float
ab: add-double
ac: sub-double
ad: mul-double
ae: div-double
af: rem-double
A: thanh ghi đích hoặc cặp (8 bit)
B: thanh ghi nguồn đầu tiên hoặc cặp (8 bit)
C: thanh ghi nguồn thứ hai hoặc cặp (8 bit)
Thực hiện thao tác nhị phân đã xác định trên hai thanh ghi nguồn, lưu trữ kết quả trong thanh ghi đích.

Lưu ý: Trái ngược với các phép toán -long khác (lấy các cặp thanh ghi cho cả nguồn đầu tiên và nguồn thứ hai của chúng), shl-long , shr- shr-longushr-long lấy một cặp thanh ghi cho nguồn đầu tiên của chúng (giá trị được dịch chuyển ), nhưng một thanh ghi duy nhất cho nguồn thứ hai của chúng (khoảng cách dịch chuyển).

b0..cf 12x binop / 2addr vA, vB
b0: add-int / 2addr
b1: sub-int / 2addr
b2: mul-int / 2addr
b3: div-int / 2addr
b4: rem-int / 2addr
b5: and-int / 2addr
b6: or-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
be: div-long / 2addr
bf: rem-long / 2addr
c0: and-long / 2addr
c1: or-long / 2addr
c2: xor-long / 2addr
c3: shl-long / 2addr
c4: shr-long / 2addr
c5: ushr-long / 2addr
c6: add-float / 2addr
c7: sub-float / 2addr
c8: mul-float / 2addr
c9: div-float / 2addr
ca: rem-float / 2addr
cb: add-double / 2addr
cc: sub-double / 2addr
cd: mul-double / 2addr
ce: div-double / 2addr
cf: rem-double / 2addr
A: đích và thanh ghi nguồn đầu tiên hoặc cặp (4 bit)
B: thanh ghi nguồn thứ hai hoặc cặp (4 bit)
Thực hiện thao tác nhị phân đã xác định trên hai thanh ghi nguồn, lưu trữ kết quả trong thanh ghi nguồn đầu tiên.

Lưu ý: Trái ngược với các phép toán -long/2addr khác (lấy các cặp thanh ghi cho cả nguồn đích / nguồn đầu tiên và nguồn thứ hai của chúng), shl-long/2addr , shr shr-long/2addrushr-long/2addr lấy một thanh ghi ghép nối cho nguồn đích / nguồn đầu tiên của chúng (giá trị được dịch chuyển), nhưng một thanh ghi cho nguồn thứ hai của chúng (khoảng cách dịch chuyển).

d0..d7 22 giây binop / lit16 vA, vB, # + CCCC
d0: add-int / lit16
d1: rsub-int (trừ ngược)
d2: mul-int / lit16
d3: div-int / lit16
d4: rem-int / lit16
d5: and-int / lit16
d6: hoặc-int / lit16
d7: xor-int / lit16
A: thanh ghi đích (4 bit)
B: thanh ghi nguồn (4 bit)
C: hằng số int có dấu (16 bit)
Thực hiện op nhị phân được chỉ định trên thanh ghi được chỉ định (đối số đầu tiên) và giá trị chữ (đối số thứ hai), lưu trữ kết quả trong thanh ghi đích.

Lưu ý: rsub-int không có hậu tố vì phiên bản này là opcode chính của họ. Ngoài ra, hãy xem bên dưới để biết chi tiết về ngữ nghĩa của nó.

d8..e2 22b binop / lit8 vAA, vBB, # + CC
d8: add-int / lit8
d9: rsub-int / lit8
da: mul-int / lit8
db: div-int / lit8
dc: rem-int / lit8
dd: and-int / lit8
de: or-int / lit8
df: xor-int / lit8
e0: shl-int / lit8
e1: shr-int / lit8
e2: ushr-int / lit8
A: thanh ghi đích (8 bit)
B: thanh ghi nguồn (8 bit)
C: hằng số int có dấu (8 bit)
Thực hiện op nhị phân được chỉ định trên thanh ghi được chỉ định (đối số đầu tiên) và giá trị chữ (đối số thứ hai), lưu trữ kết quả trong thanh ghi đích.

Lưu ý: Xem bên dưới để biết chi tiết về ngữ nghĩa của rsub-int .

e3..f9 10x (không sử dụng) (không sử dụng)
fa 45cc gọi đa hình {vC, vD, vE, vF, vG}, meth @ BBBB, proto @ HHHH A: số từ đối số (4 bit)
B: chỉ số tham chiếu phương thức (16 bit)
C: bộ thu (4 bit)
D..G: thanh ghi đối số (mỗi thanh ghi 4 bit)
H: chỉ số tham chiếu nguyên mẫu (16 bit)
Gọi phương thức đa hình chữ ký được chỉ định. Kết quả (nếu có) có thể được lưu trữ với một biến thể move-result* thích hợp làm hướng dẫn ngay sau đó.

Tham chiếu phương thức phải là phương thức đa hình chữ ký, chẳng hạn như java.lang.invoke.MethodHandle.invoke hoặc java.lang.invoke.MethodHandle.invokeExact .

Người nhận phải là một đối tượng hỗ trợ phương thức đa hình chữ ký đang được gọi.

Tham chiếu nguyên mẫu mô tả các kiểu đối số được cung cấp và kiểu trả về dự kiến.

Bytecode invoke-polymorphic có thể tăng các ngoại lệ khi nó thực thi. Các ngoại lệ được mô tả trong tài liệu API cho phương thức đa hình chữ ký đang được gọi.

Trình bày trong các tệp Dex từ phiên bản 038 trở đi.
fb 4rcc gọi đa hình / dải ô {vCCCC .. vNNNN}, meth @ BBBB, proto @ HHHH A: số từ đối số (8 bit)
B: chỉ số tham chiếu phương thức (16 bit)
C: bộ thu (16 bit)
H: chỉ số tham chiếu nguyên mẫu (16 bit)
N = A + C - 1
Gọi phương thức xử lý được chỉ định. Xem mô tả invoke-polymorphic ở trên để biết chi tiết.

Trình bày trong các tệp Dex từ phiên bản 038 trở đi.
fc 35c gọi tùy chỉnh {vC, vD, vE, vF, vG}, call_site @ BBBB A: số từ đối số (4 bit)
B: chỉ số tham chiếu trang web cuộc gọi (16 bit)
C..G: thanh ghi đối số (mỗi thanh ghi 4 bit)
Giải quyết và gọi trang web cuộc gọi được chỉ định. Kết quả từ lệnh gọi (nếu có) có thể được lưu trữ với một biến thể move-result* thích hợp làm lệnh ngay sau đó.

Lệnh này thực hiện trong hai giai đoạn: giải quyết cuộc gọi trang web và gọi trang web gọi.

Độ phân giải trang web cuộc gọi kiểm tra xem trang web cuộc gọi được chỉ định có phiên bản java.lang.invoke.CallSite được liên kết hay không. Nếu không, phương thức trình liên kết bootstrap cho địa chỉ cuộc gọi được chỉ định sẽ được gọi bằng cách sử dụng các đối số có trong tệp DEX (xem call_site_item ). Phương thức trình liên kết bootstrap trả về một cá thể java.lang.invoke.CallSite sau đó sẽ được liên kết với trang web gọi được chỉ định nếu không có liên kết nào tồn tại. Một luồng khác có thể đã thực hiện liên kết trước và nếu vậy thì việc thực thi lệnh sẽ tiếp tục với phiên bản java.lang.invoke.CallSite được liên kết đầu tiên.

Lời gọi trang web được thực hiện trên đích java.lang.invoke.MethodHandle của phiên bản java.lang.invoke.CallSite đã phân giải. Đích được gọi như thể đang thực thi lệnh invoke-polymorphic (được mô tả ở trên) bằng cách sử dụng phương thức xử lý và các đối số cho lệnh invoke-custom như các đối số cho một lệnh gọi xử lý phương thức chính xác.

Các ngoại lệ được đưa ra bởi phương thức trình liên kết bootstrap được bao bọc trong một java.lang.BootstrapMethodError . Lỗi BootstrapMethodError cũng được nâng lên nếu:
  • phương thức trình liên kết bootstrap không trả lại được phiên bản java.lang.invoke.CallSite .
  • java.lang.invoke.CallSite được trả về có mục tiêu xử lý phương thức null .
  • mục tiêu xử lý phương thức không thuộc loại được yêu cầu.
Trình bày trong các tệp Dex từ phiên bản 038 trở đi.
fd 3rc gọi ra-tùy chỉnh / phạm vi {vCCCC .. vNNNN}, call_site @ BBBB A: số từ đối số (8 bit)
B: chỉ số tham chiếu trang web cuộc gọi (16 bit)
C: thanh ghi đối số đầu tiên (16-bit)
N = A + C - 1
Giải quyết và gọi một trang web cuộc gọi. Xem mô tả invoke-custom ở trên để biết chi tiết.

Trình bày trong các tệp Dex từ phiên bản 038 trở đi.
fe 21c const-method-handle vAA, method_handle @ BBBB A: thanh ghi đích (8 bit)
B: chỉ số xử lý phương thức (16 bit)
Di chuyển một tham chiếu đến xử lý phương thức được chỉ định bởi chỉ mục đã cho vào thanh ghi được chỉ định.

Trình bày trong các tệp Dex từ phiên bản 039 trở đi.
ff 21c const-method-type vAA, proto @ BBBB A: thanh ghi đích (8 bit)
B: tham chiếu nguyên mẫu phương pháp (16 bit)
Di chuyển một tham chiếu đến nguyên mẫu phương thức được chỉ định bởi chỉ mục đã cho vào thanh ghi được chỉ định.

Trình bày trong các tệp Dex từ phiên bản 039 trở đi.

định dạng đóng gói-chuyển-tải

Tên Định dạng Sự mô tả
danh tính ushort = 0x0100 xác định mã giả chọn
kích thước ushort số lượng mục nhập trong bảng
khóa đầu tiên int giá trị trường hợp chuyển đổi đầu tiên (và thấp nhất)
mục tiêu int [] danh sách các mục tiêu chi nhánh tương đối về size . Các mục tiêu liên quan đến địa chỉ của mã chuyển đổi, không phải của bảng này.

Lưu ý: Tổng số đơn vị mã cho một phiên bản của bảng này là (size * 2) + 4 .

định dạng chuyển mạch thưa thớt

Tên Định dạng Sự mô tả
danh tính ushort = 0x0200 xác định mã giả chọn
kích thước ushort số lượng mục nhập trong bảng
chìa khóa int [] danh sách các giá trị khóa size , được sắp xếp từ thấp đến cao
mục tiêu int [] danh sách các mục tiêu nhánh tương đối về size , mỗi mục tiêu tương ứng với giá trị khóa tại cùng một chỉ mục. Các mục tiêu liên quan đến địa chỉ của mã chuyển đổi, không phải của bảng này.

Lưu ý: Tổng số đơn vị mã cho một phiên bản của bảng này là (size * 4) + 2 .

điền-mảng-dữ liệu-định dạng tải trọng

Tên Định dạng Sự mô tả
danh tính ushort = 0x0300 xác định mã giả chọn
phần tử_ width ushort số byte trong mỗi phần tử
kích thước uint số phần tử trong bảng
dữ liệu ubyte [] giá trị dữ liệu

Lưu ý: Tổng số đơn vị mã cho một phiên bản của bảng này là (size * element_width + 1) / 2 + 4 .

Chi tiết hoạt động toán học

Lưu ý: Các phép toán dấu phẩy động phải tuân theo các quy tắc IEEE 754, sử dụng quy trình làm tròn đến gần nhất và dần dần, trừ khi có quy định khác.

Opcode C Ngữ nghĩa Ghi chú
neg-int int32 a;
int32 kết quả = -a;
Bổ sung hai lá một.
not-int int32 a;
kết quả int32 = ~ a;
Phần bổ sung đơn nhất.
dài hạn int64 a;
int64 kết quả = -a;
Bổ sung hai lá một.
không lâu int64 a;
kết quả int64 = ~ a;
Phần bổ sung đơn nhất.
Neg-float phao a;
float result = -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 .