일반 디자인
- 머신 모델과 호출 규칙은 일반적인 실제 아키텍처와 C 스타일 호출 규칙을 거의 정확하게 모방하기 위한 용도입니다.
- 머신은 레지스터 기반이며 프레임은 생성 시 크기가 고정됩니다.
각 프레임은 특정 수의 레지스터(메서드로 지정됨)와 메서드를 실행하는 데 필요한 추가 데이터(예: 메서드를 포함하는
.dex
파일의 참조와 프로그램 카운터를 포함하되 이에 제한되지 않음)로 구성됩니다. - 비트 값(예: 정수 및 부동 소수점 숫자)에 사용되는 경우 레지스터는 너비가 32비트로 간주됩니다. 인접 레지스터 쌍은 64비트 값에 사용됩니다. 레지스터 쌍에 관한 정렬 필수사항은 없습니다.
- 객체 참조에 사용되는 경우 레지스터는 이러한 참조를 정확히 한 개 보유할 정도의 너비를 갖는 것으로 간주됩니다.
- 비트별 표현의 관점에서
(Object) null == (int) 0
. - 메서드의 N개 인수는 메서드 호출 프레임의 마지막 N개 레지스터에 순서대로 위치합니다. 너비가 넓은 인수는 두 개의 레지스터를 사용합니다. 인스턴스 메서드에
this
참조가 첫 번째 인수로 전달됩니다.
- 머신은 레지스터 기반이며 프레임은 생성 시 크기가 고정됩니다.
각 프레임은 특정 수의 레지스터(메서드로 지정됨)와 메서드를 실행하는 데 필요한 추가 데이터(예: 메서드를 포함하는
- 명령어 스트림의 저장용량 단위는 16비트의 부호 없는 양입니다. 일부 명령어의 몇몇 비트는 무시되거나 0이어야 합니다.
- 명령어는 근거 없이 특정 유형으로 제한되지 않습니다. 예를 들어, 해석 없이 32비트 레지스터 값을 이동하는 명령어는 정수를 이동하는지 아니면 부동 소수점 수를 이동하는지 지정할 필요가 없습니다.
- 문자열, 유형, 필드 및 메서드의 참조와 관련해 별도로 열거되고 색인이 생성된 상수 풀이 있습니다.
- 비트별 리터럴 데이터는 명령어 스트림에서 인라인으로 표현됩니다.
- 실제로 16개가 넘는 레지스터를 필요로 하는 메서드가 흔하지 않고 8개가 넘는 레지스터를 필요로 하는 경우가 상당히 흔하기 때문에 많은 명령어가 첫 16개의 레지스터만 처리하도록 제한됩니다. 가능한 경우 명령어는 최대 첫 256개의 레지스터에 관한 참조를 허용합니다. 또한 일부 명령어에는 훨씬 더 많은 레지스터 수를 허용하는 변형이 있습니다. 예를 들어,
v0
~v65535
범위에 있는 레지스터를 처리할 수 있는 catch-allmove
명령어 쌍이 이에 해당됩니다. 원하는 레지스터를 처리하는 데 명령어 변형을 사용할 수 없는 경우, 레지스터 콘텐츠를 원래 레지스터에서 낮은 레지스터(연산 전)로 이동하거나 낮은 결과 레지스터에서 높은 결과 레지스터(연산 후)로 이동해야 합니다. - 정규 명령어(예:
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 단위의 상위 바이트가 데이터 특성을 나타냅니다. 아래에서 ' |
|
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비트) |
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.
참고: |
05 22x | move-wide/from16 vAA, vBBBB | A: 대상 레지스터 쌍(8비트)B: 소스 레지스터 쌍(16비트) |
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.
참고: 구현 시 고려사항은 위 |
06 32x | move-wide/16 vAAAA, vBBBB | A: 대상 레지스터 쌍(16비트)B: 소스 레지스터 쌍(16비트) |
한 레지스터 쌍의 콘텐츠를 다른 레지스터 쌍으로 이동합니다.
참고: 구현 시 고려사항은 위 |
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가 이 명령어를 이미 통과한 것처럼 예외를 발생시켜야 합니다.
이런 상황은 명령어가 (어느 정도는) 성공적으로 실행되고 나서 예외가 발생한 것(명령어가 실행된 이후지만 다른 명령어가 실행될 기회를 얻기 전)으로 생각하는 것이 도움이 됩니다. 이 같은 정의를 통해 메서드는 광범위한 모니터 정리(예: |
1f 21c | check-cast vAA, type@BBBB | A: 참조 보유 레지스터(8비트)B: 유형 색인(16비트) |
제공된 레지스터의 참조를 표시된 유형으로 변환할 수 없는 경우 ClassCastException 을 발생시킵니다.참고: |
20 22c | instance-of vA, vB, type@CCCC | A: 대상 레지스터(4비트)B: 참조 보유 레지스터(4비트)C: 유형 색인(16비트) |
표시된 참조가 제공된 유형의 인스턴스인 경우 제공된 대상 레지스터에 1 을 저장하고 그렇지 않은 경우 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비트) |
표시된 명령어로 무조건 건너뜁니다.
참고: 분기 오프셋은 |
29 20t | goto/16 +AAAA | A: 부호 있는 분기 오프셋(16비트) |
표시된 명령어로 무조건 건너뜁니다.
참고: 분기 오프셋은 |
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 인 경우 a 를 0 으로 설정하고 b > c 인 경우 1 로, b < c 인 경우 -1 로 설정하여, 표시된 부동 소수점 또는 long 비교를 실행합니다.
부동 소수점 연산과 관해 나열된 '편향'은 NaN 비교가 처리되는 방법을 나타냅니다. 'gt bias' 명령어는 NaN 비교 시 1 을 반환하고, 'lt bias' 명령어는 -1 을 반환합니다.
예를 들어 부동 소수점 |
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비트) |
지정된 대로 제공된 두 레지스터의 값이 비교되는 경우 제공된 대상으로 분기합니다. 참고: 분기 오프셋은 |
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과 비교되는 경우 제공된 대상으로 분기합니다. 참고: 분기 오프셋은 |
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* 변형과 함께 바로 그다음의 명령어 형태로 저장될 수 있습니다.
Dex 파일 버전
참고: 이러한 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개의 소스 레지스터에서 식별된 이진 연산을 진행하고 결과를 대상 레지스터에 저장합니다. 참고: 다른 |
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비트) |
두 개의 소스 레지스터에서 식별된 이진 연산을 실행하고 결과를 첫 번째 소스 레지스터에 저장합니다. 참고: 다른 |
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이기 때문에 |
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비트) |
표시된 레지스터(첫 번째 인수)와 리터럴 값(두 번째 인수)에서 표시된 이진 연산을 실행하고 결과를 대상 레지스터에 저장합니다. 참고: |
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 가 발생합니다.
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; |
가장 가까운 값으로 반올림을 사용하여 int32 를 float 로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
|
int-to-double | int32 a; double result = (double) a; |
int32 에서 double 로 변환됩니다. |
long-to-int | int64 a; int32 result = (int32) a; |
int64 가 int32 로 잘립니다. |
long-to-float | int64 a; float result = (float) a; |
가장 가까운 값으로 반올림을 사용하여 int64 를 float 로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
|
long-to-double | int64 a; double result = (double) a; |
가장 가까운 값으로 반올림을 사용하여 int64 를 double 로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
|
float-to-int | float a; int32 result = (int32) a; |
0 방향의 가장 가까운 정수로 올림을 사용하여 float 를 int32 로 변환합니다. NaN 및 -0.0 (음수 0)은 정수 0 으로 변환됩니다. 표현하기에 크기가 너무 큰 무한대와 값은 부호에 따라 0x7fffffff 또는 -0x80000000 으로 변환됩니다.
|
float-to-long | float a; int64 result = (int64) a; |
0 방향의 가장 가까운 정수로 올림을 사용하여 float 를 int64 로 변환합니다. float-to-int 와 동일한 특별 케이스 규칙이 여기에 적용됩니다. 단, 범위를 벗어난 값은 부호에 따라 0x7fffffffffffffff 또는 -0x8000000000000000 으로 변환됩니다.
|
float-to-double | float a; double result = (double) a; |
float 를 double 로 변환하고 값은 정확하게 유지합니다. |
double-to-int | double a; int32 result = (int32) a; |
0 방향의 가장 가까운 정수로 올림을 사용하여 double 을 int32 로 변환합니다. float-to-int 와 동일한 특수 케이스 규칙이 여기에 적용됩니다.
|
double-to-long | double a; int64 result = (int64) a; |
0 방향의 가장 가까운 정수로 올림을 사용하여 double 을 int64 로 변환합니다. float-to-long 과 동일한 특수 케이스 규칙이 여기에 적용됩니다.
|
double-to-float | double a; float result = (float) a; |
가장 가까운 값으로 반올림을 사용하여 double 을 float 로 변환합니다. 이로 인해 일부 값의 정밀도가 떨어집니다.
|
int-to-byte | int32 a; int32 result = (a << 24) >> 24; |
int32 를 int8 로 자르고 결과를 부호 확장합니다. |
int-to-char | int32 a; int32 result = a & 0xffff; |
int32 를 uint16 으로 자르고 부호 확장하지 않습니다. |
int-to-short | int32 a; int32 result = (a << 16) >> 16; |
int32 를 int16 으로 자르고 결과를 부호 확장합니다. |
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 로 정의됩니다.
|