Dalvik 바이트 코드

일반 디자인

  • 머신 모델과 호출 규칙은 일반적인 실제 아키텍처와 C 스타일 호출 규칙을 거의 정확하게 모방하기 위한 용도입니다.
    • 머신은 레지스터 기반이며 프레임은 생성 시 크기가 고정됩니다. 각 프레임은 특정 수의 레지스터(메서드로 지정됨)와 메서드를 실행하는 데 필요한 추가 데이터(예: 메서드를 포함하는 .dex 파일의 참조와 프로그램 카운터를 포함하되 이에 제한되지 않음)로 구성됩니다.
    • 비트 값(예: 정수 및 부동 소수점 숫자)에 사용되는 경우 레지스터는 너비가 32비트로 간주됩니다. 인접 레지스터 쌍은 64비트 값에 사용됩니다. 레지스터 쌍에 관한 정렬 필수사항은 없습니다.
    • 객체 참조에 사용되는 경우 레지스터는 이러한 참조를 정확히 한 개 보유할 정도의 너비를 갖는 것으로 간주됩니다.
    • 비트별 표현의 관점에서 (Object) null == (int) 0.
    • 메서드의 N개 인수는 메서드 호출 프레임의 마지막 N개 레지스터에 순서대로 위치합니다. 너비가 넓은 인수는 두 개의 레지스터를 사용합니다. 인스턴스 메서드에 this 참조가 첫 번째 인수로 전달됩니다.
  • 명령어 스트림의 저장용량 단위는 16비트의 부호 없는 양입니다. 일부 명령어의 몇몇 비트는 무시되거나 0이어야 합니다.
  • 명령어는 근거 없이 특정 유형으로 제한되지 않습니다. 예를 들어, 해석 없이 32비트 레지스터 값을 이동하는 명령어는 정수를 이동하는지 아니면 부동 소수점 수를 이동하는지 지정할 필요가 없습니다.
  • 문자열, 유형, 필드 및 메서드의 참조와 관련해 별도로 열거되고 색인이 생성된 상수 풀이 있습니다.
  • 비트별 리터럴 데이터는 명령어 스트림에서 인라인으로 표현됩니다.
  • 실제로 16개가 넘는 레지스터를 필요로 하는 메서드가 흔하지 않고 8개가 넘는 레지스터를 필요로 하는 경우가 상당히 흔하기 때문에 많은 명령어가 첫 16개의 레지스터만 처리하도록 제한됩니다. 가능한 경우 명령어는 최대 첫 256개의 레지스터에 관한 참조를 허용합니다. 또한 일부 명령어에는 훨씬 더 많은 레지스터 수를 허용하는 변형이 있습니다. 예를 들어, v0~v65535 범위에 있는 레지스터를 처리할 수 있는 catch-all move 명령어 쌍이 이에 해당됩니다. 원하는 레지스터를 처리하는 데 명령어 변형을 사용할 수 없는 경우, 레지스터 콘텐츠를 원래 레지스터에서 낮은 레지스터(연산 전)로 이동하거나 낮은 결과 레지스터에서 높은 결과 레지스터(연산 후)로 이동해야 합니다.
  • 정규 명령어(예: fill-array-data)에 의해 참조되는 가변 길이 데이터 페이로드를 보유하는 데 사용되는 몇 가지 '의사 명령어'가 있습니다. 이러한 명령어는 일반적인 실행 흐름 중에 발생해서는 안 됩니다. 또한 명령어는 짝수 바이트 코드 오프셋에 배치(즉, 4바이트 정렬)되어야 합니다. 이 요구사항을 충족하려면 dex 생성 도구에서 추가 nop 명령어를 공백으로 내보내야 합니다(그러지 않으면 이러한 명령어는 정렬되지 않음). 마지막으로 필수사항은 아니지만 대부분의 도구는 메서드 끝에서 이러한 명령어를 내보내도록 선택해야 합니다. 그러지 않으면 이러한 명령어에서 분기하는 데 추가 명령어가 필요할 수 있기 때문입니다.
  • 실행 중인 시스템에 설치된 경우 일부 명령어가 수정되어 형식이 설치 시간 정적 연결 최적화로 변경될 수 있습니다. 인식된 연결인 경우 이를 통해 더 빠른 실행이 가능합니다. 제안된 변형과 관련된 명령어 형식 문서를 참조하세요. '제안'이라는 표현을 사용한 이유는 이러한 변형을 구현하는 것이 필수사항은 아니기 때문입니다.
  • 인간 구문 및 니모닉:
    • 인수를 대상-소스 순서로 배열.
    • 일부 opcode는 연산되는 유형을 나타내기 위해 명확한 이름 접미사를 사용합니다.
      • 유형 일반의 32비트 opcode는 표시가 해제되어 있습니다.
      • 유형 일반의 64비트 opcode에는 -wide가 접미사로 붙어 있습니다.
      • 유형 특정의 opcode에는 -boolean -byte -char -short -int -long -float -double -object -string -class -void 중 한 유형(또는 간단한 약어)이 접미사로 붙어 있습니다.
    • 일부 opcode에는 다른 명령어 레이아웃 또는 옵션을 가진 연산(그렇지 않으면 동일한 연산)을 구분하기 위한 명확한 접미사가 붙어 있습니다. 이러한 접미사는 기본 이름과 슬래시('/')로 구분되고, 주된 용도는 실행 파일을 생성하고 해석하는 코드에서 정적 상수와 일대일 매핑을 만드는 것(즉, 인간에게 모호함을 덜 주기 위한 목적)입니다.
    • 여기에 나와 있는 설명에서 값의 너비(정수의 범위 또는 처리되었을 수 있는 레지스터 개수 등을 나타냄)는 4비트 너비마다 문자를 사용하여 강조됩니다.
    • 예를 들어 'move-wide/from16 vAA, vBBBB' 명령어에서
      • 'move'는 기본 연산을 나타내는 기본 opcode입니다(레지스터의 값 이동).
      • 'wide'는 너비가 64비트인 데이터에서 연산됨을 나타내는 이름 접미사입니다.
      • 'from16'은 16비트 레지스터 참조를 소스로 갖는 변형을 나타내는 opcode 접미사입니다.
      • 'vAA'는 대상 레지스터(연산에 나타남. 즉, 대상 인수가 항상 먼저 오도록 규칙이 적용됨)이고, v0~v255 범위 내에 있어야 합니다.
      • 'vBBBB'는 소스 레지스터이고 v0~v65535 범위 내에 있어야 합니다.
  • opcode 구문과 다양한 명령어 형식('Op 및 형식'에 나열되어 있음)에 관한 자세한 내용은 명령어 형식 문서를 참조하세요.
  • 바이트 코드가 전체적으로 어떻게 활용되는지에 관한 자세한 내용은 .dex 파일 형식 문서를 참조하세요.

바이트 코드 세트 요약

Op 및 형식 니모닉/구문 인수 설명
00 10x nop   폐기물 처리 주기

참고: 데이터 보유 의사 명령어는 이 opcode로 태그가 지정됩니다. 이 경우 opcode 단위의 상위 바이트가 데이터 특성을 나타냅니다. 아래에서 'packed-switch-payload 형식', 'sparse-switch-payload 형식' 및 'fill-array-data-payload 형식'을 참조하세요.

01 12x move vA, vB A: 대상 레지스터(4비트)
B: 소스 레지스터(4비트)
한 비객체 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
02 22x move/from16 vAA, vBBBB A: 대상 레지스터(8비트)
B: 소스 레지스터(16비트)
한 비객체 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
03 32x move/16 vAAAA, vBBBB A: 대상 레지스터(16비트)
B: 소스 레지스터(16비트)
한 비객체 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
04 12x move-wide vA, vB A: 대상 레지스터 쌍(4비트)
B: 소스 레지스터 쌍(4비트)
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.

참고: vN에서 vN-1 또는 vN+1 중 하나로 이동하는 것이 허용됩니다. 따라서 구현 시 무언가가 작성되기 전에 레지스터 쌍의 양쪽 모두를 읽도록 해야 합니다.

05 22x move-wide/from16 vAA, vBBBB A: 대상 레지스터 쌍(8비트)
B: 소스 레지스터 쌍(16비트)
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.

참고: 구현 시 고려사항은 위 move-wide와 동일합니다.

06 32x move-wide/16 vAAAA, vBBBB A: 대상 레지스터 쌍(16비트)
B: 소스 레지스터 쌍(16비트)
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.

참고: 구현 시 고려사항은 위 move-wide와 동일합니다.

07 12x move-object vA, vB A: 대상 레지스터(4비트)
B: 소스 레지스터(4비트)
한 객체 보유 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
08 22x move-object/from16 vAA, vBBBB A: 대상 레지스터(8비트)
B: 소스 레지스터(16비트)
한 객체 보유 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
09 32x move-object/16 vAAAA, vBBBB A: 대상 레지스터(16비트)
B: 소스 레지스터(16비트)
한 객체 보유 레지스터의 콘텐츠를 다른 레지스터로 이동합니다.
0a 11x move-result vAA A: 대상 레지스터(8비트) 가장 최근 invoke-kind의 단일 워드 비객체 결과를 표시된 레지스터로 이동합니다. 이 작업은 단일 워드, 비객체 결과가 무시되지 않는 invoke-kind 바로 다음에 명령어 형태로 실행되어야 합니다. 다른 위치에서는 무효합니다.
0b 11x move-result-wide vAA A: 대상 레지스터 쌍(8비트) 가장 최근 invoke-kind의 이중 워드 결과를 표시된 레지스터 쌍으로 이동합니다. 이 작업은 이중 워드 결과가 무시되지 않는 invoke-kind 바로 다음에 명령어 형태로 실행되어야 합니다. 다른 위치에서는 무효합니다.
0c 11x move-result-object vAA A: 대상 레지스터(8비트) 가장 최근 invoke-kind의 객체 결과를 표시된 레지스터로 이동합니다. 이 작업은 객체 결과가 무시되지 않는 invoke-kind 또는 filled-new-array 바로 다음에 명령어 형태로 실행되어야 합니다. 다른 위치에서는 무효합니다.
0d 11x move-exception vAA A: 대상 레지스터(8비트) 방금 감지된 예외를 지정된 레지스터에 저장합니다. 이는 감지된 예외가 무시되지 않는 예외 핸들러의 첫 번째 명령어여야 하고, 이 명령어는 예외 핸들러의 첫 번째 명령어로 발생해야 합니다. 다른 위치에서는 무효합니다.
0e 10x return-void   void 메서드에서 반환합니다.
0f 11x return vAA A:는 값 레지스터(8비트)를 반환함 단일 너비(32비트)의 비객체 값 반환 메서드에서 반환합니다.
10 11x return-wide vAA A:는 값 레지스터 쌍(8비트)을 반환함 이중 너비(64비트)의 값 반환 메서드에서 반환합니다.
11 11x return-object vAA A:는 값 레지스터(8비트)를 반환함 객체 반환 메서드에서 반환합니다.
12 11n const/4 vA, #+B A: 대상 레지스터(4비트)
B: 부호 있는 int(4비트)
제공된 리터럴 값(32비트로 부호 확장됨)을 지정된 레지스터로 이동합니다.
13 21s const/16 vAA, #+BBBB A: 대상 레지스터(8비트)
B: 부호 있는 int(16비트)
제공된 리터럴 값(32비트로 부호 확장됨)을 지정된 레지스터로 이동합니다.
14 31i const vAA, #+BBBBBBBB A: 대상 레지스터(8비트)
B: 임의의 32비트 상수
제공된 리터럴 값을 지정된 레지스터로 이동합니다.
15 21h const/high16 vAA, #+BBBB0000 A: 대상 레지스터(8비트)
B: 부호 있는 int(16비트)
제공된 리터럴 값(32비트로 오른쪽으로 제로 확장됨)을 지정된 레지스터로 이동합니다.
16 21s const-wide/16 vAA, #+BBBB A: 대상 레지스터(8비트)
B: 부호 있는 int(16비트)
제공된 리터럴 값(64비트로 부호 확장됨)을 지정된 레지스터 쌍으로 이동합니다.
17 31i const-wide/32 vAA, #+BBBBBBBB A: 대상 레지스터(8비트)
B: 부호 있는 int(32비트)
제공된 리터럴 값(64비트로 부호 확장됨)을 지정된 레지스터 쌍으로 이동합니다.
18 51l const-wide vAA, #+BBBBBBBBBBBBBBBB A: 대상 레지스터(8비트)
B: 임의의 이중 너비(64비트) 상수
제공된 리터럴 값을 지정된 레지스터 쌍으로 이동합니다.
19 21h const-wide/high16 vAA, #+BBBB000000000000 A: 대상 레지스터(8비트)
B: 부호 있는 int(16비트)
제공된 리터럴 값(64비트로 오른쪽으로 제로 확장됨)을 지정된 레지스터 쌍으로 이동합니다.
1a 21c const-string vAA, string@BBBB A: 대상 레지스터(8비트)
B: 문자열 색인
제공된 색인으로 지정된 문자열의 참조를 지정된 레지스터로 이동합니다.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: 대상 레지스터(8비트)
B: 문자열 색인
제공된 색인으로 지정된 문자열의 참조를 지정된 레지스터로 이동합니다.
1c 21c const-class vAA, type@BBBB A: 대상 레지스터(8비트)
B: 유형 색인
제공된 색인으로 지정된 클래스의 참조를 지정된 레지스터로 이동합니다. 표시된 유형이 기본 유형인 경우 기본 유형의 변질 클래스 참조를 저장합니다.
1d 11x monitor-enter vAA A: 참조 보유 레지스터(8비트) 표시된 객체의 모니터를 가져옵니다.
1e 11x monitor-exit vAA A: 참조 보유 레지스터(8비트) 표시된 객체의 모니터를 해제합니다.

참고: 이 명령어가 예외를 발생시켜야 하는 경우 pc가 이 명령어를 이미 통과한 것처럼 예외를 발생시켜야 합니다. 이런 상황은 명령어가 (어느 정도는) 성공적으로 실행되고 나서 예외가 발생한 것(명령어가 실행된 이후지만 다른 명령어가 실행될 기회를 얻기 )으로 생각하는 것이 도움이 됩니다. 이 같은 정의를 통해 메서드는 광범위한 모니터 정리(예: finally) 블록을 블록 자체에 관한 모니터 정리로 사용하여 이전의 Thread.stop() 구현으로 발생할 수 있는 임의 예외를 처리하고, 동시에 모니터 상태가 적절하도록 관리할 수도 있습니다.

1f 21c check-cast vAA, type@BBBB A: 참조 보유 레지스터(8비트)
B: 유형 색인(16비트)
제공된 레지스터의 참조를 표시된 유형으로 변환할 수 없는 경우 ClassCastException을 발생시킵니다.

참고: A가 항상 원시 값이 아닌 참조여야 하기 때문에, B가 기본 유형을 참조하는 경우 런타임 시 필연적으로 오류가 발생합니다(즉, 예외 발생).

20 22c instance-of vA, vB, type@CCCC A: 대상 레지스터(4비트)
B: 참조 보유 레지스터(4비트)
C: 유형 색인(16비트)
표시된 참조가 제공된 유형의 인스턴스인 경우 제공된 대상 레지스터에 1을 저장하고 그렇지 않은 경우 0을 저장합니다.

참고: B가 항상 원시 값이 아닌 참조여야 하기 때문에, C가 원시 유형을 참조하는 경우 항상 0이 저장됩니다.

21 12x array-length vA, vB A: 대상 레지스터(4비트)
B: 배열 참조 보유 레지스터(4비트)
항목에 표시된 배열의 길이를 제공된 대상 레지스터에 저장합니다.
22 21c new-instance vAA, type@BBBB A: 대상 레지스터(8비트)
B: 유형 색인
표시된 유형의 새 인스턴스를 생성하고 새 인스턴스의 참조를 대상에 저장합니다. 유형은 비배열 클래스를 참조해야 합니다.
23 22c new-array vA, vB, type@CCCC A: 대상 레지스터(4비트)
B: 크기 레지스터
C: 유형 색인
표시된 유형과 크기로 구성된 새 배열을 생성합니다. 유형은 배열 유형이어야 합니다.
24 35c filled-new-array {vC, vD, vE, vF, vG}, type@BBBB A: 배열 크기 및 인수 워드 수(4비트)
B: 유형 색인(16비트)
C..G: 인수 레지스터(각 4비트)
제공된 유형과 크기로 구성된 배열을 생성하고 제공된 콘텐츠로 배열을 채웁니다. 유형은 배열 유형이어야 합니다. 배열의 콘텐츠는 단일 워드여야 합니다. 즉, long 또는 double로 구성된 배열은 아니지만 참조 유형은 허용됩니다. 생성된 인스턴스는 메서드 호출 명령어가 결과를 저장하는 방식과 동일하게 '결과'로 저장됩니다. 따라서 생성된 인스턴스는 바로 그다음의 move-result-object 명령어(사용되는 경우)를 통해 레지스터로 이동되어야 합니다.
25 3rc filled-new-array/range {vCCCC .. vNNNN}, type@BBBB A: 배열 크기 및 인수 워드 수(8비트)
B: 유형 색인(16비트)
C: 첫 번째 인수 레지스터(16비트)
N = A + C - 1
제공된 유형과 크기로 구성된 배열을 생성하고 제공된 콘텐츠로 배열을 채웁니다. 설명과 제한사항은 위에 설명한 filled-new-array와 동일합니다.
26 31t fill-array-data vAA, +BBBBBBBB (아래의 'fill-array-data-payload 형식'에 지정된 추가 데이터 포함) A: 배열 참조(8비트)
B: 테이블 데이터 의사 명령어(32비트)의 부호 있는 '분기' 오프셋
제공된 배열을 표시된 데이터로 채 웁니다. 참조는 원시 값으로 구성된 배열이어야 하고, 데이터 테이블은 유형이 배열과 일치해야 하며 그 배열에 적합한 요소 개수보다 더 많은 요소를 포함해서는 안 됩니다. 즉, 배열은 테이블보다 클 수 있으며, 배열이 테이블보다 큰 경우 배열의 초기 요소만 설정되고 나머지는 그대로 둡니다.
27 11x throw vAA A: 예외 보유 레지스터(8비트)
표시된 예외를 발생시킵니다.
28 10t goto +AA A: 부호 있는 분기 오프셋(8비트) 표시된 명령어로 무조건 건너뜁니다.

참고: 분기 오프셋은 0이 아니어야 합니다. 스핀 루프는 goto/32를 사용하거나 nop을 분기 전 타겟으로 포함하여 생성하는 것이 바람직할 수 있습니다.

29 20t goto/16 +AAAA A: 부호 있는 분기 오프셋(16비트)
표시된 명령어로 무조건 건너뜁니다.

참고: 분기 오프셋은 0이 아니어야 합니다. 스핀 루프는 goto/32를 사용하거나 nop을 분기 전 타겟으로 포함하여 생성하는 것이 바람직할 수 있습니다.

2a 30t goto/32 +AAAAAAAA A: 부호 있는 분기 오프셋(32비트)
표시된 명령어로 무조건 건너뜁니다.
2b 31t packed-switch vAA, +BBBBBBBB(아래의 'packed-switch-payload 형식'에 지정된 추가 데이터 포함) A: 테스트할 레지스터
B: 테이블 데이터 의사 명령어의 부호 있는 '분기' 오프셋(32비트)
특정 정수 범위의 각 값에 상응하는 오프셋 테이블을 사용하여 제공된 레지스터의 값에 따라 새 명령어로 이동하거나, 일치하는 항목이 없는 경우 그다음 명령어로 이동합니다.
2c 31t sparse-switch vAA, +BBBBBBBB(아래에 'sparse-switch-payload 형식'에 지정된 추가 데이터 포함) A: 테스트할 레지스터
B: 테이블 데이터 의사 명령어의 부호 있는 '분기' 오프셋(32비트)
정렬된 값-오프셋 쌍 테이블을 사용하여 제공된 레지스터의 값에 따라 새 명령어로 이동하거나, 일치하는 항목이 없는 경우 그다음 명령어로 이동합니다.
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: 대상 레지스터(8비트)
B: 첫 번째 소스 레지스터 또는 쌍
C: 두 번째 소스 레지스터 또는 쌍
b == c인 경우 a0으로 설정하고 b > c인 경우 1로, b < c인 경우 -1로 설정하여, 표시된 부동 소수점 또는 long 비교를 실행합니다. 부동 소수점 연산과 관해 나열된 '편향'은 NaN 비교가 처리되는 방법을 나타냅니다. 'gt bias' 명령어는 NaN 비교 시 1을 반환하고, 'lt bias' 명령어는 -1을 반환합니다.

예를 들어 부동 소수점 x < y인지 확인하려면 cmpg-float를 사용하는 것이 좋습니다. 결과가 -1인 경우 테스트가 참이었음을 나타내고, 다른 값인 경우에는 유효한 비교 또는 값 중 하나가 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: 테스트할 첫 번째 레지스터(4비트)
B: 테스트할 두 번째 레지스터(4비트)
C: 부호 있는 분기 오프셋(16비트)
지정된 대로 제공된 두 레지스터의 값이 비교되는 경우 제공된 대상으로 분기합니다.

참고: 분기 오프셋은 0이 아니어야 합니다. 스핀 루프는 역방향 goto를 중심으로 분기하거나 nop을 분기 전 타겟으로 포함하여 생성하는 것이 바람직할 수 있습니다.

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
A: 테스트할 레지스터(8비트)
B: 부호 있는 분기 오프셋(16비트)
지정된 대로 제공된 레지스터의 값이 0과 비교되는 경우 제공된 대상으로 분기합니다.

참고: 분기 오프셋은 0이 아니어야 합니다. 스핀 루프는 역방향 goto를 중심으로 분기하거나 nop을 분기 전 타겟으로 포함하여 생성하는 것이 바람직할 수 있습니다.

3e..43 10x (사용되지 않음)   (사용되지 않음)
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
A: 값 레지스터 또는 쌍. 소스 또는 대상일 수 있음(8비트)
B: 배열 레지스터(8비트)
C: 색인 레지스터(8비트)
제공된 배열의 식별된 색인에서 식별된 배열 연산을 실행하여 값 레지스터에 로드하거나 저장합니다.
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
A: 값 레지스터 또는 쌍. 소스 또는 대상일 수 있음(4비트)
B: 객체 레지스터(4비트)
C: 인스턴스 필드 참조 색인(16비트)
식별된 필드에서 식별된 객체 인스턴스 필드 연산을 진행하고 그 값을 로드하거나 값 레지스터에 저장합니다.

참고: 이러한 opcode는 필드 인수를 더 직접적인 오프셋으로 변경하기 때문에 정적 연결에 적합합니다.

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: 값 레지스터 또는 쌍. 소스 또는 대상일 수 있음(8비트)
B: 정적 필드 참조 색인(16비트)
식별된 정적 필드에서 식별된 객체 정적 필드 연산을 진행하고 그 값을 로드하거나 값 레지스터에 저장합니다.

참고: 이러한 opcode는 필드 인수를 더 직접적인 오프셋으로 변경하기 때문에 정적 연결에 적합합니다.

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
A: 인수 워드 수(4비트)
B: 메서드 참조 색인(16비트)
C..G: 인수 레지스터(각 4비트)
표시된 메서드를 호출합니다. 결과(있는 경우)는 적절한 move-result* 변형과 함께 바로 그다음의 명령어 형태로 저장될 수 있습니다.

invoke-virtual은 일반 가상 메서드(private, static 또는 final이 아니며 생성자도 아닌 메서드)를 호출하는 데 사용됩니다.

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-staticstatic 메서드(예외없이 직접 메서드로 간주됨)를 호출하는 데 사용됩니다.

invoke-interfaceinterface를 참조하는 method_id를 사용하여 구체적 클래스가 인식되지 않은 객체에 관한 interface 메서드를 호출하는 데 사용됩니다.

참고: 이러한 opcode는 메서드 인수를 더 직접적인 오프셋(또는 그 오프셋의 쌍)으로 변경하기 때문에 정적 연결에 적합합니다.

73 10x (사용되지 않음)   (사용되지 않음)
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: 인수 워드 수(8비트)
B: 메서드 참조 색인(16비트)
C: 첫 번째 인수 레지스터(16비트)
N = A + C - 1
표시된 메서드를 호출합니다. 세부정보, 주의사항 및 제안사항은 위에서 첫 번째 invoke-kind 설명을 참조하세요.
79..7a 10x (사용되지 않음)   (사용되지 않음)
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: 대상 레지스터 또는 쌍(4비트)
B: 소스 레지스터 또는 쌍(4비트)
소스 레지스터에서 식별된 단항 연산을 실행하여 결과를 대상 레지스터에 저장합니다.
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: 대상 레지스터 또는 쌍(8비트)
B: 첫 번째 소스 레지스터 또는 쌍(8비트)
C: 두 번째 소스 레지스터 또는 쌍(8비트)
2개의 소스 레지스터에서 식별된 이진 연산을 진행하고 결과를 대상 레지스터에 저장합니다.

참고: 다른 -long 수학 연산(첫 번째 소스와 두 번째 소스 모두에 레지스터 쌍을 취함)과 반대로 shl-long, shr-longushr-long은 첫 번째 소스(이동할 값)에는 레지스터 쌍을 취하지만 두 번째 소스(이동 거리)에는 단일 레지스터를 취합니다.

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: 대상 및 첫 번째 소스 레지스터 또는 쌍(4비트)
B: 두 번째 소스 레지스터 또는 쌍(4비트)
두 개의 소스 레지스터에서 식별된 이진 연산을 실행하고 결과를 첫 번째 소스 레지스터에 저장합니다.

참고: 다른 -long/2addr 수학 연산(대상/첫 번째 소스와 두 번째 소스 모두에 레지스터 쌍을 취함)과 반대로 shl-long/2addr, shr-long/2addrushr-long/2addr은 대상/첫 번째 소스(이동할 값)에는 레지스터 쌍을 취하지만 두 번째 소스(이동 거리)에는 단일 레지스터를 취합니다.

d0..d7 22s binop/lit16 vA, vB, #+CCCC
d0: add-int/lit16
d1: rsub-int (reverse subtract)
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: 대상 레지스터(4비트)
B: 소스 레지스터(4비트)
C: 부호 있는 int 상수(16비트)
표시된 레지스터(첫 번째 인수)와 리터럴 값(두 번째 인수)에서 표시된 이진 연산을 실행하고 결과를 대상 레지스터에 저장합니다.

참고: 이 버전이 계열의 주요 opcode이기 때문에 rsub-int는 접미사를 갖지 않습니다. 또한 의미 체계에 관한 세부정보는 아래를 참조하세요.

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: 대상 레지스터(8비트)
B: 소스 레지스터(8비트)
C: 부호 있는 int 상수(8비트)
표시된 레지스터(첫 번째 인수)와 리터럴 값(두 번째 인수)에서 표시된 이진 연산을 실행하고 결과를 대상 레지스터에 저장합니다.

참고: rsub-int의 의미 체계에 관한 세부정보는 아래를 참조하세요.

e3..f9 10x (사용되지 않음)   (사용되지 않음)
fa 45cc invoke-polymorphic {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.invoke 또는 java.lang.invoke.MethodHandle.invokeExact와 같은 서명 다형성 메서드의 참조여야 합니다.

수신자는 호출되는 서명 다형성 메서드를 지원하는 객체여야 합니다.

프로토타입 참조는 제공된 인수 유형과 예상되는 반환 유형을 설명합니다.

invoke-polymorphic 바이트 코드는 실행 시 예외를 발생시킬 수 있습니다. 호출되는 서명 다형성 메서드와 관련된 예외는 API 문서에 설명되어 있습니다.

버전 038부터 Dex 파일에 있습니다.
fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: 인수 워드 수(8비트)
B: 메서드 참조 색인(16비트)
C: 수신자(16비트)
H: 프로토타입 참조 색인(16비트)
N = A + C - 1
지정된 메서드 핸들을 호출합니다. 세부정보는 위에서 invoke-polymorphic 설명을 참조하세요.

버전 038부터 Dex 파일에 있습니다.
fc 35c invoke-custom {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(위에 설명됨)을 실행 중인 것처럼 대상이 호출됩니다.

부트스트랩 링커 메서드에서 발생하는 예외는 java.lang.BootstrapMethodError로 래핑됩니다. 다음 경우에도 BootstrapMethodError가 발생합니다.
  • 부트스트랩 링커 메서드가 java.lang.invoke.CallSite 인스턴스 반환에 실패하는 경우.
  • 반환된 java.lang.invoke.CallSitenull 메서드 핸들 대상이 있는 경우.
  • 메서드 핸들 대상이 요청된 유형이 아닌 경우.
버전 038부터 Dex 파일에 있습니다.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: 인수 워드 수(8비트)
B: 호출 사이트 참조 색인(16비트)
C: 첫 번째 인수 레지스터(16비트)
N = A + C - 1
호출 사이트를 확인하고 호출합니다. 세부정보는 위에서 invoke-custom 설명을 참조하세요.

버전 038부터 Dex 파일에 있습니다.
fe 21c const-method-handle vAA, method_handle@BBBB A: 대상 레지스터(8비트)
B: 메서드 핸들 색인(16비트)
제공된 색인으로 지정된 메서드 핸들의 참조를 지정된 레지스터로 이동합니다.

버전 039부터 Dex 파일에 있습니다.
ff 21c const-method-type vAA, proto@BBBB A: 대상 레지스터(8비트)
B: 메서드 프로토타입 참조(16비트)
제공된 색인으로 지정된 메서드 프로토타입의 참조를 지정된 레지스터로 이동합니다.

버전 039부터 Dex 파일에 있습니다.

packed-switch-payload 형식

이름 형식 설명
ident ushort = 0x0100 의사 opcode 식별
size ushort 테이블의 항목 수
first_key int 첫 번째 및 최저 스위치 케이스 값
targets int[] size 상대적 분기 대상의 목록. 타겟은 이 테이블의 주소가 아닌 스위치 opcode의 주소를 기준으로 합니다.

참고: 이 테이블의 인스턴스에 관한 총 코드 단위 개수는 (size * 2) + 4입니다.

sparse-switch-payload 형식

이름 형식 설명
ident ushort = 0x0200 의사 opcode 식별
size ushort 테이블의 항목 수
keys int[] 낮은 값에서 높은 값으로 정렬된 size 키 값의 목록
targets int[] size 상대적 분기 대상의 목록으로, 각 대상은 동일한 색인에 있는 키 값에 해당합니다. 타겟은 이 테이블의 주소가 아닌 스위치 opcode의 주소를 기준으로 합니다.

참고: 이 테이블의 인스턴스에 관한 총 코드 단위 개수는 (size * 4) + 2입니다.

fill-array-data-payload 형식

이름 형식 설명
ident ushort = 0x0300 의사 opcode 식별
element_width ushort 각 요소의 바이트 수
size uint 테이블의 요소 수
데이터 ubyte[] 데이터 값

참고: 이 테이블의 인스턴스에 관한 총 코드 단위 개수는 (size * element_width + 1) / 2 + 4입니다.

수학 연산 세부정보

참고: 부동 소수점 연산은 다르게 명시된 경우를 제외하고 가장 가까운 값으로 반올림 및 점진적 언더플로를 사용하는 IEEE 754 규칙을 따라야 합니다.

명령 코드 C 의미 체계 메모
neg-int int32 a;
int32 result = -a;
단항 2의 보수
not-int int32 a;
int32 result = ~a;
단항 1의 보수
neg-long int64 a;
int64 result = -a;
단항 2의 보수
not-long int64 a;
int64 result = ~a;
단항 1의 보수
neg-float float a;
float result = -a;
부동 소수점 부정
neg-double double a;
double result = -a;
부동 소수점 부정
int-to-long int32 a;
int64 result = (int64) a;
int32에서 int64로 부호 확장.
int-to-float int32 a;
float result = (float) a;
가장 가까운 값으로 반올림을 사용하여 int32float로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
int-to-double int32 a;
double result = (double) a;
int32에서 double로 변환됩니다.
long-to-int int64 a;
int32 result = (int32) a;
int64int32로 잘립니다.
long-to-float int64 a;
float result = (float) a;
가장 가까운 값으로 반올림을 사용하여 int64float로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
long-to-double int64 a;
double result = (double) a;
가장 가까운 값으로 반올림을 사용하여 int64double로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
float-to-int float a;
int32 result = (int32) a;
0 방향의 가장 가까운 정수로 올림을 사용하여 floatint32로 변환합니다. NaN-0.0(음수 0)은 정수 0으로 변환됩니다. 표현하기에 크기가 너무 큰 무한대와 값은 부호에 따라 0x7fffffff 또는 -0x80000000으로 변환됩니다.
float-to-long float a;
int64 result = (int64) a;
0 방향의 가장 가까운 정수로 올림을 사용하여 floatint64로 변환합니다. float-to-int와 동일한 특별 케이스 규칙이 여기에 적용됩니다. 단, 범위를 벗어난 값은 부호에 따라 0x7fffffffffffffff 또는 -0x8000000000000000으로 변환됩니다.
float-to-double float a;
double result = (double) a;
floatdouble로 변환하고 값은 정확하게 유지합니다.
double-to-int double a;
int32 result = (int32) a;
0 방향의 가장 가까운 정수로 올림을 사용하여 doubleint32로 변환합니다. float-to-int와 동일한 특수 케이스 규칙이 여기에 적용됩니다.
double-to-long double a;
int64 result = (int64) a;
0 방향의 가장 가까운 정수로 올림을 사용하여 doubleint64로 변환합니다. float-to-long과 동일한 특수 케이스 규칙이 여기에 적용됩니다.
double-to-float double a;
float result = (float) a;
가장 가까운 값으로 반올림을 사용하여 doublefloat로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
int32int8로 자르고 결과를 부호 확장합니다.
int-to-char int32 a;
int32 result = a & 0xffff;
int32uint16으로 자르고 부호 확장하지 않습니다.
int-to-short int32 a;
int32 result = (a << 16) >> 16;
int32int16으로 자르고 결과를 부호 확장합니다.
add-int int32 a, b;
int32 result = a + b;
2의 보수 덧셈
sub-int int32 a, b;
int32 result = a - b;
2의 보수 뺄셈
rsub-int int32 a, b;
int32 result = b - a;
2의 보수 역뺄셈
mul-int int32 a, b;
int32 result = a * b;
2의 보수 곱셈
div-int int32 a, b;
int32 result = a / b;
2의 보수 나눗셈. 0 방향의 가장 가까운 정수로 올립니다(즉, 정수로 잘림). b == 0인 경우 ArithmeticException이 발생합니다.
rem-int int32 a, b;
int32 result = a % b;
나눗셈의 2의 보수 나머지. 결과의 부호는 a의 부호와 동일하고, result == a - (a / b) * b로 더 정확하게 정의됩니다. b == 0인 경우 ArithmeticException이 발생합니다.
and-int int32 a, b;
int32 result = a & b;
비트별 AND
or-int int32 a, b;
int32 result = a | b;
비트별 OR
xor-int int32 a, b;
int32 result = a ^ b;
비트별 XOR
shl-int int32 a, b;
int32 result = a << (b & 0x1f);
비트별로 왼쪽 이동(인수는 마스크 처리됨)
shr-int int32 a, b;
int32 result = a >> (b & 0x1f);
비트별로 오른쪽으로 부호 있는 이동(인수는 마스크 처리됨)
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
비트별로 오른쪽으로 부호 없는 이동(인수는 마스크 처리됨)
add-long int64 a, b;
int64 result = a + b;
2의 보수 덧셈
sub-long int64 a, b;
int64 result = a - b;
2의 보수 뺄셈
mul-long int64 a, b;
int64 result = a * b;
2의 보수 곱셈
div-long int64 a, b;
int64 result = a / b;
2의 보수 나눗셈. 0 방향의 가장 가까운 정수로 올립니다(즉, 정수로 잘림). b == 0인 경우 ArithmeticException이 발생합니다.
rem-long int64 a, b;
int64 result = a % b;
나눗셈의 2의 보수 나머지. 결과의 부호는 a의 부호와 동일하고, result == a - (a / b) * b로 더 정확하게 정의됩니다. b == 0인 경우 ArithmeticException이 발생합니다.
and-long int64 a, b;
int64 result = a & b;
비트별 AND
or-long int64 a, b;
int64 result = a | b;
비트별 OR
xor-long int64 a, b;
int64 result = a ^ b;
비트별 XOR
shl-long int64 a;
int32 b;
int64 result = a << (b & 0x3f);
비트별로 왼쪽 이동(인수는 마스크 처리됨)
shr-long int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
비트별로 오른쪽으로 부호 있는 이동(인수는 마스크 처리됨)
ushr-long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
비트별로 오른쪽으로 부호 없는 이동(인수는 마스크 처리됨)
add-float float a, b;
float result = a + b;
부동 소수점 덧셈
sub-float float a, b;
float result = a - b;
부동 소수점 뺄셈
mul-float float a, b;
float result = a * b;
부동 소수점 곱셈
div-float float a, b;
float result = a / b;
부동 소수점 나눗셈
rem-float float a, b;
float result = a % b;
나눗셈의 부동소수점 나머지. 이 함수는 IEEE 754 나머지와 다르고 result == a - roundTowardZero(a / b) * b로 정의됩니다.
add-double double a, b;
double result = a + b;
부동 소수점 덧셈
sub-double double a, b;
double result = a - b;
부동 소수점 뺄셈
mul-double double a, b;
double result = a * b;
부동 소수점 곱셈
div-double double a, b;
double result = a / b;
부동 소수점 나눗셈
rem-double double a, b;
double result = a % b;
나눗셈의 부동소수점 나머지. 이 함수는 IEEE 754 나머지와 다르고 result == a - roundTowardZero(a / b) * b로 정의됩니다.