Định dạng mã byte Dalvik

Thiết kế chung

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

Tóm tắt về tập hợp mã byte

Toán tử và định dạng Thuật nhớ / Cú pháp Đối số Mô tả
00 10x nop   Chu kỳ chất thải.

Lưu ý: Các lệnh giả mang dữ liệu được gắn thẻ bằng mã opcode này, trong đó, byte thứ tự 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 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 sang một thanh ghi khác.
02 22x move/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 không phải đối tượng sang một thanh ghi khác.
03 32x move/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 sang một thanh ghi khác.
04 12x vA, vB trên toàn bộ thao tác di chuyển Cặp thanh ghi đích A: (4 bit)
Cặp thanh ghi nguồn B: (4 bit)
Di chuyển nội dung của một cặp thanh ghi sang một cặp thanh ghi khác.

Lưu ý: Bạn có thể chuyển từ vN sang vN-1 hoặc vN+1, vì vậy, quá trình triển khai phải sắp xếp để đọc cả hai nửa của một cặp thanh ghi trước khi ghi bất kỳ nội dung nào.

05 22x move-wide/from16 vAA, vBBBB Cặp thanh ghi đích A: (8 bit)
Cặp thanh ghi nguồn B: (16 bit)
Di chuyển nội dung của một cặp thanh ghi sang một cặp thanh ghi khác.

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

06 32x move-wide/16 vAAAA, vBBBB Cặp thanh ghi đích A: (16 bit)
Cặp thanh ghi nguồn B: (16 bit)
Di chuyển nội dung của một cặp thanh ghi sang một cặp thanh ghi khác.

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

07 12x move-object 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 chứa đối tượng sang một thanh ghi 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 chứa đối tượng sang một thanh ghi 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 chứa đối tượng sang một thanh ghi khác.
0a 11x move-result vAA A: thanh ghi đích (8 bit) Di chuyển kết quả không phải đối tượng gồm một từ của invoke-kind gần đây nhất vào thanh ghi được chỉ định. Bạn phải thực hiện việc này dưới dạng hướng dẫn ngay sau một invoke-kind có kết quả (một từ, không phải đối tượng) không được bỏ qua; mọi vị trí khác đều không hợp lệ.
0b 11x move-result-wide vAA Cặp thanh ghi đích A: (8 bit) Di chuyển kết quả từ hai từ của invoke-kind gần đây nhất vào cặp thanh ghi được chỉ định. Bạn phải thực hiện việc này dưới dạng hướng dẫn ngay sau một invoke-kind có kết quả (từ đôi) không được bỏ qua; mọi vị trí khác đều 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 invoke-kind gần đây nhất vào thanh ghi được chỉ định. Bạn phải thực hiện việc này dưới dạng hướng dẫn ngay sau invoke-kind hoặc filled-new-array có kết quả (đối tượng) không được bỏ qua; mọi vị trí khác đều không hợp lệ.
0 ngày 11 lần move-exception vAA A: thanh ghi đích (8 bit) Lưu một ngoại lệ vừa phát hiện 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ệ đã phát hiện không được bỏ qua và lệnh này chỉ được xuất hiện dưới dạng lệnh đầu tiên của trình xử lý ngoại lệ; mọi vị trí khác đều không hợp lệ.
0e 10x return-void   Trả về từ một phương thức void.
11x trả về vAA A: thanh ghi giá trị trả về (8 bit) Trả về từ một phương thức trả về giá trị không phải đối tượng có chiều rộng đơn (32 bit).
10 11x vAA trên toàn lượt trả về Cặp thanh ghi giá trị trả về A: (8 bit) Trả về từ một phương thức trả về giá trị có chiều rộng gấp đôi (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 đã ký (4 bit)
Di chuyển giá trị cố định đã cho (mở rộng dấu thành 32 bit) vào thanh ghi đã chỉ định.
13 21 giây const/16 vAA, #+BBBB A: thanh ghi đích (8 bit)
B: số nguyên có dấu (16 bit)
Di chuyển giá trị cố định đã cho (mở rộng dấu thành 32 bit) vào thanh ghi đã chỉ định.
14 31i const vAA, #+BBBBBBBB A: thanh ghi đích (8 bit)
B: hằng số 32 bit tuỳ ý
Di chuyển giá trị cố định đã cho vào thanh ghi đã chỉ định.
15 21h const/high16 vAA, #+BBBB0000 A: thanh ghi đích (8 bit)
B: số nguyên có dấu (16 bit)
Di chuyển giá trị cố định đã cho (mở rộng về bên phải bằng 0 thành 32 bit) vào thanh ghi đã chỉ định.
16 21 giây const-wide/16 vAA, #+BBBB A: thanh ghi đích (8 bit)
B: số nguyên có dấu (16 bit)
Di chuyển giá trị cố định đã cho (mở rộng dấu thành 64 bit) vào cặp thanh ghi đã chỉ định.
17 31i const-wide/32 vAA, #+BBBBBBBB A: thanh ghi đích (8 bit)
B: số nguyên có dấu (32 bit)
Di chuyển giá trị cố định đã cho (mở rộng dấu thành 64 bit) vào cặp thanh ghi đã chỉ định.
18 51l const-wide vAA, #+BBBBBBBBBBBBBBBB A: thanh ghi đích (8 bit)
B: hằng số chiều rộng đôi tuỳ ý (64 bit)
Di chuyển giá trị cố định đã cho vào cặp thanh ghi đã chỉ định.
19 21h const-wide/high16 vAA, #+BBBB000000000000 A: thanh ghi đích (8 bit)
B: số nguyên có dấu (16 bit)
Di chuyển giá trị cố định đã cho (được mở rộng về bên phải bằng 0 thành 64 bit) vào cặp thanh ghi đã chỉ định.
1a 21c const-string vAA, string@BBBB A: thanh ghi đích (8 bit)
B: chỉ mục chuỗi
Di chuyển tệp tham chiếu đến chuỗi do chỉ mục đã cho chỉ định vào thanh ghi đã chỉ định.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: thanh ghi đích (8 bit)
B: chỉ mục chuỗi
Di chuyển tệp tham chiếu đến chuỗi do chỉ mục đã cho chỉ định vào đăng ký đã chỉ định.
1c 21c const-class vAA, type@BBBB thanh ghi đích A: (8 bit)
chỉ mục loại B:
Di chuyển một tệp tham chiếu đến lớp được chỉ định theo chỉ mục đã cho vào đăng ký đã chỉ định. Trong trường hợp loại được chỉ định là loại nguyên gốc, lớp này sẽ lưu trữ một tham chiếu đến lớp thoái hoá của loại nguyên gốc.
1 ngày 11 lần monitor-enter vAA A: thanh ghi chứa tham chiếu (8 bit) Thu nạp màn hình cho đối tượng được chỉ định.
1e 11x monitor-exit vAA A: thanh ghi chứa tham chiếu (8 bit) Giải phóng màn hình cho đối tượng được chỉ định.

Lưu ý: Nếu cần gửi một ngoại lệ, lệnh này phải thực hiện như thể máy tính đã vượt qua lệnh. Bạn có thể xem đây là hướng dẫn thực thi thành công (theo một nghĩa nào đó) và ngoại lệ được gửi sau hướng dẫn nhưng trước khi hướng dẫn tiếp theo có cơ hội chạy. Định nghĩa này cho phép một phương thức sử dụng tính năng tổng hợp dọn dẹp màn hình (ví dụ: finally) 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ệ tuỳ ý có thể được gửi do quá trình triển khai Thread.stop() trước đây, trong khi vẫn quản lý để có chế độ vệ sinh màn hình thích hợp.

1f 21c check-cast vAA, type@BBBB A: thanh ghi chứa tham chiếu (8 bit)
chỉ mục loại B: (16 bit)
Gửi một ClassCastException nếu không thể truyền tham chiếu trong đăng ký đã cho sang loại được chỉ định.

Lưu ý:A phải luôn là một tệp tham chiếu (và không phải là một giá trị gốc), nên việc này chắc chắn sẽ không thành công trong thời gian chạy (tức là sẽ gửi một ngoại lệ) nếu B tham chiếu đến một loại gốc.

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

Lưu ý:B phải luôn là một tệp tham chiếu (và không phải là một giá trị gốc), nên đ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 loại gốc.

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

Lưu ý: Độ dời nhánh không được là 0. (Bạn có thể tạo vòng lặp spin một cách hợp pháp bằng goto/32 hoặc bằng cách đưa nop vào làm mục tiêu trước nhánh.)

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

Lưu ý: Độ dời nhánh không được là 0. (Bạn có thể tạo vòng lặp spin một cách hợp pháp bằng goto/32 hoặc bằng cách đưa nop vào làm mục tiêu trước nhánh.)

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

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

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

Lưu ý: Độ dời nhánh không được là 0. (Bạn có thể tạo vòng lặp spin một cách hợp pháp bằng cách phân nhánh xung quanh goto ngược hoặc bằng cách đưa nop vào làm mục tiêu trước nhánh.)

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

Lưu ý: Độ dời nhánh không được là 0. (Bạn có thể tạo vòng lặp spin một cách hợp pháp bằng cách phân nhánh xung quanh goto ngược hoặc bằng cách đưa nop vào làm mục tiêu trước nhánh.)

3e..43 10x (không dùng)   (không 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: aget-short
4b: aput
4c: aput-wide
4d: aput-object
4e: aput-boolean
4f: aput-byte
50: aput-char
51: aput-short
Đăng ký giá trị hoặc cặp A:; có thể là nguồn hoặc đích (8 bit)
B: đăng ký mảng (8 bit)
C: đăng ký chỉ mục (8 bit)
Thực hiện phép toán trên 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 iinstanceop vA, vB, field@CCCC
52: iget
53: iget-wide
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
Đăng ký giá trị hoặc cặp A:; có thể là nguồn hoặc đích (4 bit)
đăng ký đối tượng B: (4 bit)
chỉ mục tham chiếu trường thực thể C: (16 bit)
Thực hiện thao tác trường thực thể đối tượng đã xác định bằng trường đã xác định, tải hoặc lưu vào thanh ghi giá trị.

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

60..6d 21c sstaticop vAA, field@BBBB
60: sget
61: sget-wide
62: sget-object
63: sget-boolean
64: sget-byte
65: sget-char
66: sget-short
67: sput
68: sput-wide
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ỉ mục tham chiếu trường tĩnh (16 bit)
Thực hiện thao tác trường tĩnh của đối tượng đã xác định bằng trường tĩnh đã xác định, tải hoặc lưu vào thanh ghi giá trị.

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

6e..72 35c invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB
6e: invoke-virtual
6f: invoke-super
70: invoke-direct
71: invoke-static
72: invoke-interface
Số từ đối số A: (4 bit)
Chỉ mục tham chiếu phương thức B: (16 bit)
Bộ đăng ký đối số C..G: (mỗi bộ đăng ký 4 bit)
Gọi phương thức được chỉ định. Kết quả (nếu có) có thể được lưu trữ bằng một biến thể move-result* thích hợp làm lệnh tiếp theo ngay lập tức.

invoke-virtual được dùng để gọi một phương thức ảo thông thường, là một phương thức không phải static, private hoặc hàm khởi tạo.

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

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

invoke-direct được dùng để gọi một phương thức trực tiếp không phải static (tức là một phương thức thực thể theo bản chất không thể ghi đè, cụ thể là phương thức thực thể private hoặc hàm khởi tạo).

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

invoke-interface được dùng để gọi một phương thức interface, tức là trên một đối tượng có lớp cụ thể không xác định, sử dụng method_id tham chiếu đến interface.

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

73 10x (không dùng)   (không dùng)
74..78 3rc invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB
74: invoke-virtual/range
75: invoke-super/range
76: invoke-direct/range
77: invoke-static/range
78: invoke-interface/range
A: số từ đối số (8 bit)
B: chỉ mục 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 thức được chỉ định. Hãy xem phần mô tả invoke-kind đầu tiên ở trên để biết thông tin chi tiết, lưu ý và đề xuất.
79..7a 10x (không dùng)   (không dùng)
7b..8f 12x unop vA, vB
7b: neg-int
7c: not-int
7d: neg-long
7e: not-long
7f: neg-float
80: neg-double
81: int-to-long
82: int-to-float
83: int-to-double
84: long-to-int
85: long-to-float
86: long-to-double
87: float-to-int
88: float-to-long
89: float-to-double
8a: double-to-int
8b: double-to-long
8c: double-to-float
8d: int-to-byte
8e: int-to-char
8f: int-to-short
A: bộ nhớ đích hoặc cặp (4 bit)
B: bộ nhớ nguồn hoặc cặp (4 bit)
Thực hiện phép toán một ngôi đã 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: sub-int
92: mul-int
93: div-int
94: rem-int
95: and-int
96: or-int
97: xor-int
98: shl-int
99: shr-int
9a: ushr-int
9b: add-long
9c: sub-long
9d: mul-long
9e: div-long
9f: rem-long
a0: and-long
a1: or-long
a2: xor-long
a3: shl-long
a4: shr-long
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: cặp hoặc thanh ghi đích (8 bit)
B: cặp hoặc thanh ghi nguồn đầu tiên (8 bit)
C: cặp hoặc thanh ghi nguồn thứ hai (8 bit)
Thực hiện phép toán 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 ý: Ngược với các phép toán -long khác (lấy cặp thanh ghi cho cả nguồn đầu tiên và nguồn thứ hai), shl-long, shr-longushr-long lấy một cặp thanh ghi cho nguồn đầu tiên (giá trị cần dịch chuyển) nhưng chỉ lấy một thanh ghi cho nguồn thứ hai (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 phép toán 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 ý: Ngược với các phép toán -long/2addr khác (lấy cặp thanh ghi cho cả đích đến/nguồn đầu tiên và nguồn thứ hai), shl-long/2addr, shr-long/2addrushr-long/2addr lấy một cặp thanh ghi cho đích đến/nguồn đầu tiên (giá trị cần dịch chuyển), nhưng chỉ lấy một thanh ghi cho nguồn thứ hai (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 (phép trừ đảo)
d2: mul-int/lit16
d3: div-int/lit16
d4: rem-int/lit16
d5: and-int/lit16
d6: or-int/lit16
d7: xor-int/lit16
A: thanh ghi đích (4 bit)
B: thanh ghi nguồn (4 bit)
C: hằng số int đã ký (16 bit)
Thực hiện toán tử nhị phân được chỉ định trên thanh ghi được chỉ định (đối số đầu tiên) và giá trị cố định (đố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à toán tử chính của gia đình. Ngoài ra, hãy xem phần bên dưới để biết thông tin chi tiết về ngữ nghĩa của hàm này.

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 đã ký (8 bit)
Thực hiện toán tử nhị phân được chỉ định trên thanh ghi được chỉ định (đối số đầu tiên) và giá trị cố định (đối số thứ hai), lưu trữ kết quả trong thanh ghi đích.

Lưu ý: Hãy xem bên dưới để biết thông tin chi tiết về ngữ nghĩa của rsub-int.

e3..f9 10x (không dùng)   (không dùng)
fa 45cc invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: số từ đối số (4 bit)
B: chỉ mục tham chiếu phương thức (16 bit)
C: trình nhận (4 bit)
D..G: thanh ghi đối số (mỗi thanh ghi 4 bit)
H: chỉ mục 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ữ bằng một biến thể move-result* thích hợp làm lệnh tiếp theo ngay lập tức.

Tham chiếu phương thức phải là đến một 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.

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

Tài liệu tham khảo nguyên mẫu mô tả các loại đối số được cung cấp và loại dữ liệu trả về dự kiến.

Mã byte invoke-polymorphic có thể tạo ra ngoại lệ khi thực thi. Các trường hợp 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.

Có trong các tệp Dex từ phiên bản 038 trở lên.
fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: số từ đối số (8 bit)
B: chỉ mục tham chiếu phương thức (16 bit)
C: trình nhận (16 bit)
H: chỉ mục tham chiếu nguyên mẫu (16 bit)
N = A + C - 1
Gọi tay cầm phương thức được chỉ định. Hãy xem nội dung mô tả invoke-polymorphic ở trên để biết thông tin chi tiết.

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

Hướng dẫn này thực thi theo hai giai đoạn: phân giải vị trí gọi và gọi vị trí gọi.

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

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

Ngoại lệ do phương thức trình liên kết khởi động tạo ra được gói trong java.lang.BootstrapMethodError. BootstrapMethodError cũng được nâng lên nếu:
  • phương thức trình liên kết khởi động không trả về một thực thể 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 đã yêu cầu.
Có trong các tệp Dex từ phiên bản 038 trở lên.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: số từ đối số (8 bit)
B: chỉ mục tham chiếu vị trí 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 vị trí gọi. Hãy xem nội dung mô tả invoke-custom ở trên để biết thông tin chi tiết.

Có 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ỉ mục xử lý phương thức (16 bit)
Di chuyển tệp tham chiếu đến tay cầm phương thức do chỉ mục đã cho chỉ định vào thanh ghi đã chỉ định.

Có 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 thức (16 bit)
Di chuyển tệp tham chiếu đến nguyên mẫu phương thức do chỉ mục đã cho chỉ định vào đăng ký đã chỉ định.

Có trong các tệp Dex từ phiên bản 039 trở đi.

định dạng packed-switch-payload

Tên Định dạng Mô tả
ident ushort = 0x0100 xác định mã giả
size ushort số mục nhập trong bảng
first_key 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 nhánh tương đối size. Các mục tiêu này tương ứng với địa chỉ của mã opcode của nút chuyển, chứ không phải của bảng này.

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

định dạng tải trọng chuyển đổi thưa

Tên Định dạng Mô tả
ident ushort = 0x0200 xác định mã giả
size ushort số mục nhập trong bảng
khoá int[] danh sách các giá trị khoá 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 size, mỗi mục tiêu tương ứng với giá trị khoá ở cùng một chỉ mục. Các mục tiêu này tương ứng với địa chỉ của mã opcode của nút chuyển, chứ không phải của bảng này.

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

định dạng fill-array-data-payload

Tên Định dạng Mô tả
ident ushort = 0x0300 xác định mã giả
element_width ushort số byte trong mỗi phần tử
size uint số lượng phần tử trong bảng
data ubyte[] giá trị dữ liệu

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

Thông tin chi tiết về phép toán

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

Mã opcode Ngữ nghĩa C Ghi chú
neg-int int32 a;
int32 result = -a;
Số nguyên dấu phẩy động bổ trợ hai.
not-int int32 a;
int32 result = ~a;
Số nguyên một chiều.
neg-long int64 a;
int64 result = -a;
Số nguyên một chiều bổ trợ hai.
not-long int64 a;
int64 result = ~a;
Số nguyên một chiều.
số thực dấu phẩy động âm float a;
float result = -a;
Biểu thức phủ định dấu phẩy động.
neg-double double a;
double result = -a;
Biểu thức phủ định dấu phẩy động.
int-to-long int32 a;
int64 result = (int64) a;
Mở rộng chữ ký của int32 thành int64.
int-to-float int32 a;
float result = (float) a;
Chuyển đổi int32 thành float, sử dụng tính năng làm tròn đến số gần nhất. Điều này làm giảm độ chính xác cho một số giá trị.
int-to-double int32 a;
double result = (double) a;
Chuyển đổi int32 thành double.
long-to-int int64 a;
int32 result = (int32) a;
Cắt bớt int64 thành int32.
long-to-float int64 a;
float result = (float) a;
Chuyển đổi int64 thành float, sử dụng tính năng làm tròn đến số gần nhất. Điều này làm giảm độ chính xác cho một số giá trị.
long-to-double int64 a;
double result = (double) a;
Chuyển đổi int64 thành double, sử dụng tính năng làm tròn đến số gần nhất. Điều này làm giảm độ chính xác cho một số giá trị.
float-to-int float a;
int32 result = (int32) a;
Chuyển đổi float thành int32, sử dụng tính năng làm tròn về 0. NaN-0.0 (0 âm) chuyển đổi thành số nguyên 0. Giá trị vô cực và giá trị có độ lớn quá lớn để biểu thị sẽ được chuyển đổi thành 0x7fffffff hoặc -0x80000000 tuỳ thuộc vào dấu.
float-to-long float a;
int64 result = (int64) a;
Chuyển đổi float thành int64, sử dụng tính năng làm tròn về 0. Các quy tắc trường hợp đặc biệt tương tự như đối với float-to-int sẽ áp dụng ở đây, ngoại trừ việc các giá trị nằm ngoài phạm vi sẽ được chuyển đổi thành 0x7fffffffffffffff hoặc -0x8000000000000000 tuỳ thuộc vào dấu.
float-to-double float a;
double result = (double) a;
Chuyển đổi float thành double, giữ nguyên giá trị một cách chính xác.
double-to-int double a;
int32 result = (int32) a;
Chuyển đổi double thành int32, sử dụng tính năng làm tròn về 0. Các quy tắc trường hợp đặc biệt tương tự như đối với float-to-int cũng áp dụng ở đây.
double-to-long double a;
int64 result = (int64) a;
Chuyển đổi double thành int64, sử dụng tính năng làm tròn về 0. Các quy tắc trường hợp đặc biệt tương tự như đối với float-to-long cũng áp dụng ở đây.
double-to-float double a;
float result = (float) a;
Chuyển đổi double thành float, sử dụng tính năng làm tròn đến số gần nhất. Điều này làm giảm độ chính xác cho một số giá trị.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
Cắt bớt int32 thành int8, ký hiệu mở rộng kết quả.
int-to-char int32 a;
int32 result = a & 0xffff;
Cắt bớt int32 thành uint16, mà không cần mở rộng dấu.
int-to-short int32 a;
int32 result = (a << 16) >> 16;
Cắt bớt int32 thành int16, ký hiệu mở rộng kết quả.
add-int int32 a, b;
int32 result = a + b;
Cộng hai bổ sung.
sub-int int32 a, b;
int32 result = a - b;
Phép trừ bổ sung hai.
rsub-int int32 a, b;
int32 result = b - a;
Trừ đảo ngược bổ sung hai.
mul-int int32 a, b;
int32 result = a * b;
Nhân bổ trợ hai.
div-int int32 a, b;
int32 result = a / b;
Phép chia bổ trợ hai, làm tròn về 0 (tức là bị cắt bớt thành số nguyên). Thao tác này sẽ gửi ArithmeticException nếu b == 0.
rem-int int32 a, b;
int32 result = a % b;
Phần dư bổ trợ hai sau khi chia. Dấu của kết quả giống với dấu của a và được xác định chính xác hơn là result == a - (a / b) * b. Thao tác này sẽ gửi ArithmeticException nếu b == 0.
and-int int32 a, b;
int32 result = a & b;
Toán tử AND bit.
or-int int32 a, b;
int32 result = a | b;
Đảo bit OR.
xor-int int32 a, b;
int32 result = a ^ b;
XOR bit.
shl-int int32 a, b;
int32 result = a << (b & 0x1f);
Di chuyển bit sang trái (với đối số được che).
shr-int int32 a, b;
int32 result = a >> (b & 0x1f);
Chuyển sang phải đã ký bit (với đối số được che).
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
Di chuyển sang phải không dấu theo bit (với đối số được che).
add-long int64 a, b;
int64 result = a + b;
Cộng hai bổ sung.
dài int64 a, b;
int64 result = a - b;
Phép trừ bổ sung hai.
mul-long int64 a, b;
int64 result = a * b;
Nhân bổ trợ hai.
div-long int64 a, b;
int64 result = a / b;
Phép chia bổ trợ hai, làm tròn về 0 (tức là bị cắt bớt thành số nguyên). Thao tác này sẽ gửi ArithmeticException nếu b == 0.
rem-long int64 a, b;
int64 result = a % b;
Phần dư bổ trợ hai sau khi chia. Dấu của kết quả giống với dấu của a và được xác định chính xác hơn là result == a - (a / b) * b. Thao tác này sẽ gửi ArithmeticException nếu b == 0.
and-long int64 a, b;
int64 result = a & b;
Toán tử AND bit.
or-long int64 a, b;
int64 result = a | b;
Đảo bit OR.
xor-long int64 a, b;
int64 result = a ^ b;
XOR bit.
shl-long int64 a;
int32 b;
int64 result = a << (b & 0x3f);
Di chuyển bit sang trái (với đối số được che).
shr-long int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Chuyển sang phải đã ký bit (với đối số được che).
ushr-long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Di chuyển sang phải không dấu theo bit (với đối số được che).
add-float float a, b;
float result = a + b;
Cộng dấu phẩy động.
float phụ float a, b;
float result = a - b;
Phép trừ dấu phẩy động.
mul-float float a, b;
float result = a * b;
Nhân dấu phẩy động.
div-float float a, b;
float result = a / b;
Phép chia dấu phẩy động.
rem-float float a, b;
float result = a % b;
Số dư dấu phẩy động sau khi chia. Hàm này khác với số dư IEEE 754 và được xác định là result == a - roundTowardZero(a / b) * b.
add-double double a, b;
double result = a + b;
Cộng dấu phẩy động.
sub-double double a, b;
double result = a - b;
Phép trừ dấu phẩy động.
mul-double double a, b;
double result = a * b;
Nhân dấu phẩy động.
div-double double a, b;
double result = a / b;
Phép chia dấu phẩy động.
rem-double double a, b;
double result = a % b;
Số dư dấu phẩy động sau khi chia. Hàm này khác với phần dư IEEE 754 và được xác định là result == a - roundTowardZero(a / b) * b.