Código de bytes de Dalvik

Diseño general

  • El modelo de máquina y las convenciones de llamadas están destinados a imitar aproximadamente las arquitecturas reales comunes y las convenciones de llamadas de estilo C:
    • La máquina se basa en registros y los marcos tienen un tamaño fijo al momento de la creación. Cada cuadro consta de una cantidad particular de registros (especificados por el método), así como cualquier dato adjunto necesario para ejecutar el método, como (entre otros) el contador del programa y una referencia al archivo .dex que contiene el método. .
    • Cuando se utilizan para valores de bits (como números enteros y números de punto flotante), los registros se consideran de 32 bits de ancho. Los pares de registros adyacentes se utilizan para valores de 64 bits. No hay ningún requisito de alineación para los pares de registros.
    • Cuando se utilizan para referencias a objetos, los registros se consideran lo suficientemente amplios como para contener exactamente una de esas referencias.
    • En términos de representación bit a bit, (Object) null == (int) 0 .
    • Los N argumentos de un método aterrizan en los últimos N registros del marco de invocación del método, en orden. Los argumentos anchos consumen dos registros. Los métodos de instancia se pasan a this referencia como su primer argumento.
  • La unidad de almacenamiento en el flujo de instrucciones es una cantidad sin signo de 16 bits. Algunos bits en algunas instrucciones se ignoran/deben ser cero.
  • Las instrucciones no se limitan gratuitamente a un tipo particular. Por ejemplo, las instrucciones que mueven valores de registro de 32 bits sin interpretación no tienen que especificar si mueven números enteros o flotantes.
  • Hay conjuntos de constantes enumerados e indexados por separado para referencias a cadenas, tipos, campos y métodos.
  • Los datos literales bit a bit se representan en línea en el flujo de instrucciones.
  • Debido a que, en la práctica, es poco común que un método necesite más de 16 registros, y debido a que es razonablemente común necesitar más de ocho registros, muchas instrucciones se limitan a abordar solo los primeros 16 registros. Cuando sea razonablemente posible, las instrucciones permiten referencias hasta los primeros 256 registros. Además, algunas instrucciones tienen variantes que permiten recuentos de registros mucho más grandes, incluido un par de instrucciones de move generales que pueden abordar registros en el rango v0v65535 . En los casos en que una variante de instrucción no esté disponible para abordar un registro deseado, se espera que el contenido del registro se mueva del registro original a un registro bajo (antes de la operación) y/o se mueva de un registro de resultado bajo a uno alto. registro (después de la operación).
  • Hay varias "pseudoinstrucciones" que se utilizan para contener cargas útiles de datos de longitud variable, a las que se hace referencia mediante instrucciones normales (por ejemplo, fill-array-data ). Dichas instrucciones nunca deben encontrarse durante el flujo normal de ejecución. Además, las instrucciones deben estar ubicadas en desplazamientos de bytecode con números pares (es decir, alineados en 4 bytes). Para cumplir con este requisito, las herramientas de generación dex deben emitir una instrucción nop adicional como espaciador si, de lo contrario, dicha instrucción no estaría alineada. Finalmente, aunque no es obligatorio, se espera que la mayoría de las herramientas opten por emitir estas instrucciones al final de los métodos, ya que, de lo contrario, es probable que se necesiten instrucciones adicionales para bifurcarlas.
  • Cuando se instala en un sistema en ejecución, algunas instrucciones pueden modificarse, cambiando su formato, como una optimización de enlace estático en el momento de la instalación. Esto es para permitir una ejecución más rápida una vez que se conoce el vínculo. Consulte el documento de formatos de instrucciones asociado para ver las variantes sugeridas. La palabra "sugerido" se usa deliberadamente; no es obligatorio implementarlos.
  • Sintaxis humana y mnemónicos:
    • Ordenación destino-luego-fuente para argumentos.
    • Algunos códigos de operación tienen un sufijo de nombre que elimina la ambigüedad para indicar los tipos en los que operan:
      • Los códigos de operación de tipo general de 32 bits no están marcados.
      • Los códigos de operación de tipo general de 64 bits tienen el sufijo -wide .
      • Los códigos de operación específicos del tipo tienen como sufijo su tipo (o una abreviatura sencilla), uno de los siguientes: -boolean -byte -char -short -int -long -float -double -object -class -string -void
    • Algunos códigos de operación tienen un sufijo de eliminación de ambigüedades para distinguir operaciones idénticas que tienen diferentes diseños u opciones de instrucciones. Estos sufijos se separan de los nombres principales con una barra inclinada (" / ") y existen principalmente para que haya un mapeo uno a uno con constantes estáticas en el código que genera e interpreta los ejecutables (es decir, para reducir la ambigüedad para humanos).
    • En las descripciones aquí, el ancho de un valor (que indica, por ejemplo, el rango de una constante o el número de registros posiblemente direccionados) se enfatiza mediante el uso de un carácter por cada cuatro bits de ancho.
    • Por ejemplo, en la instrucción " move-wide/from16 vAA, vBBBB ":
      • " move " es el código de operación base, que indica la operación base (mover el valor de un registro).
      • " wide " es el sufijo del nombre, lo que indica que opera en datos anchos (64 bits).
      • " from16 " es el sufijo del código de operación, que indica una variante que tiene una referencia de registro de 16 bits como fuente.
      • " vAA " es el registro de destino (implicado por la operación; nuevamente, la regla es que los argumentos de destino siempre van primero), que debe estar en el rango v0v255 .
      • " vBBBB " es el registro de origen, que debe estar en el rango v0v65535 .
  • Consulte el documento de formatos de instrucciones para obtener más detalles sobre los diversos formatos de instrucciones (enumerados en "Op & Format"), así como detalles sobre la sintaxis del código de operación.
  • Consulte el documento de formato de archivo .dex para obtener más detalles sobre dónde encaja el código de bytes en el panorama general.

Resumen del conjunto de códigos de bytes

Op. y formato Nemónico / Sintaxis Argumentos Descripción
00 10x nop Ciclos de residuos.

Nota: las pseudoinstrucciones que contienen datos se etiquetan con este código de operación, en cuyo caso el byte de orden superior de la unidad del código de operación indica la naturaleza de los datos. Consulte "Formato packed-switch-payload ", "Formato de carga útil sparse-switch-payload " y "Formato fill-array-data-payload " a continuación.

01 12x mover vA, vB A: registro de destino (4 bits)
B: registro fuente (4 bits)
Mueve el contenido de un registro que no es de objeto a otro.
02 22x mover/desde16 vaA, vBBBB A: registro de destino (8 bits)
B: registro fuente (16 bits)
Mueve el contenido de un registro que no es de objeto a otro.
03 32x mover/16 vAAAA, vBBBB A: registro de destino (16 bits)
B: registro fuente (16 bits)
Mueve el contenido de un registro que no es de objeto a otro.
04 12x movimiento amplio vA, vB A: par de registros de destino (4 bits)
B: par de registros fuente (4 bits)
Mueve el contenido de un par de registros a otro.

Nota: es legal pasar de v N a v N-1 o v N+1 , por lo que las implementaciones deben organizar que ambas mitades de un par de registros se lean antes de escribir algo.

05 22x movimiento amplio/desde 16 vAA, vBBBB A: par de registros de destino (8 bits)
B: par de registros fuente (16 bits)
Mueve el contenido de un par de registros a otro.

Nota: Las consideraciones de implementación son las mismas que las de move-wide , arriba.

06 32x movimiento amplio/16 vAAAA, vBBBB A: par de registros de destino (16 bits)
B: par de registros fuente (16 bits)
Mueve el contenido de un par de registros a otro.

Nota: Las consideraciones de implementación son las mismas que las de move-wide , arriba.

07 12x mover-objeto vA, vB A: registro de destino (4 bits)
B: registro fuente (4 bits)
Mueva el contenido de un registro portador de objetos a otro.
08 22x mover-objeto/desde16 vaA, vBBBB A: registro de destino (8 bits)
B: registro fuente (16 bits)
Mueva el contenido de un registro portador de objetos a otro.
09 32x mover-objeto/16 vAAAA, vBBBB A: registro de destino (16 bits)
B: registro fuente (16 bits)
Mueva el contenido de un registro portador de objetos a otro.
0a 11x resultado de movimiento vAA A: registro de destino (8 bits) Mueva el resultado no objeto de una sola palabra del invoke- kind más reciente al registro indicado. Esto debe hacerse como la instrucción inmediatamente después de un invoke- kind cuyo resultado (palabra única, no objeto) no debe ignorarse; cualquier otro lugar no es válido.
0b 11x mover-resultado-ancho vAA A: par de registros de destino (8 bits) Mueva el resultado de palabra doble del invoke- kind más reciente al par de registros indicado. Esto debe hacerse como la instrucción inmediatamente después de un invoke- kind cuyo resultado (palabra doble) no debe ignorarse; cualquier otro lugar no es válido.
0c 11x mover-resultado-objeto vAA A: registro de destino (8 bits) Mueve el resultado del objeto del invoke- kind más reciente al registro indicado. Esto debe hacerse como la instrucción inmediatamente después de un invoke- kind o filled-new-array cuyo resultado (objeto) no debe ignorarse; cualquier otro lugar no es válido.
0d 11x movimiento-excepción vAA A: registro de destino (8 bits) Guarde una excepción recién capturada en el registro dado. Esta debe ser la primera instrucción de cualquier controlador de excepciones cuya excepción capturada no deba ignorarse, y esta instrucción solo debe ocurrir como la primera instrucción de un controlador de excepciones; cualquier otro lugar no es válido.
0e 10x retorno-vacío Regreso de un método void .
0f 11x devolver VAA A: registro de valor de retorno (8 bits) Retorno de un método de retorno de valor sin objeto de ancho único (32 bits).
10 11x VAA de retorno amplio A: par de registros de valor devuelto (8 bits) Retorno de un método de retorno de valor de ancho doble (64 bits).
11 11x objeto devuelto vAA A: registro de valor de retorno (8 bits) Retorno de un método de devolución de objetos.
12 11n constante/4 vA, #+B A: registro de destino (4 bits)
B: int firmado (4 bits)
Mueva el valor literal dado (con signo extendido a 32 bits) al registro especificado.
13 21s constante/16 vaA, #+BBBB A: registro de destino (8 bits)
B: int firmado (16 bits)
Mueva el valor literal dado (con signo extendido a 32 bits) al registro especificado.
14 31i constante vAA, #+BBBBBBBB A: registro de destino (8 bits)
B: constante arbitraria de 32 bits
Mueve el valor literal dado al registro especificado.
15 21h constante/alto16 vaA, #+BBBB0000 A: registro de destino (8 bits)
B: int firmado (16 bits)
Mueva el valor literal dado (derecho-cero-extendido a 32 bits) al registro especificado.
16 21s const-wide/16 vaA, #+BBBB A: registro de destino (8 bits)
B: int firmado (16 bits)
Mueva el valor literal dado (con signo extendido a 64 bits) al par de registros especificado.
17 31i const-wide/32 vaA, #+BBBBBBBB A: registro de destino (8 bits)
B: int firmado (32 bits)
Mueva el valor literal dado (con signo extendido a 64 bits) al par de registros especificado.
18 51l vAA constante, #+BBBBBBBBBBBBBBBB A: registro de destino (8 bits)
B: constante arbitraria de doble ancho (64 bits)
Mueva el valor literal dado al par de registros especificado.
19 21h const-wide/high16 vAA, #+BBBB000000000000 A: registro de destino (8 bits)
B: int firmado (16 bits)
Mueva el valor literal dado (cero a la derecha extendido a 64 bits) al par de registros especificado.
1a 21c const-cadena vAA, cadena@BBBB A: registro de destino (8 bits)
B: índice de cadena
Mueva una referencia a la cadena especificada por el índice dado en el registro especificado.
1b 31c cadena constante/jumbo vAA, cadena@BBBBBBBB A: registro de destino (8 bits)
B: índice de cadena
Mueva una referencia a la cadena especificada por el índice dado en el registro especificado.
1c 21c vAA de clase constante, tipo @ BBBB A: registro de destino (8 bits)
B: índice de tipo
Mueva una referencia a la clase especificada por el índice dado en el registro especificado. En caso de que el tipo indicado sea primitivo, almacenará una referencia a la clase degenerada del tipo primitivo.
1d 11x monitorear-ingresar vAA A: registro de referencia (8 bits) Adquirir el monitor para el objeto indicado.
1e 11x salida del monitor vAA A: registro de referencia (8 bits) Suelte el monitor para el objeto indicado.

Nota: si esta instrucción necesita lanzar una excepción, debe hacerlo como si la PC ya hubiera avanzado más allá de la instrucción. Puede ser útil pensar en esto como la instrucción que se ejecuta con éxito (en cierto sentido), y la excepción que se lanza después de la instrucción, pero antes de que la siguiente tenga la oportunidad de ejecutarse. Esta definición hace posible que un método use un bloque catch-all de limpieza del monitor (p. ej., finally ) como la limpieza del monitor para ese bloque en sí, como una forma de manejar las excepciones arbitrarias que pueden generarse debido a la implementación histórica de Thread.stop() , al mismo tiempo que logra tener una higiene adecuada del monitor.

1f 21c Verifique el lanzamiento de vAA, escriba @ BBBB A: registro de referencia (8 bits)
B: índice de tipo (16 bits)
Lance una ClassCastException si la referencia en el registro dado no se puede convertir al tipo indicado.

Nota: dado que A siempre debe ser una referencia (y no un valor primitivo), esto necesariamente fallará en tiempo de ejecución (es decir, generará una excepción) si B se refiere a un tipo primitivo.

20 22c instancia de vA, vB, type@CCCC A: registro de destino (4 bits)
B: registro portador de referencia (4 bits)
C: índice de tipo (16 bits)
Almacene en el registro de destino dado 1 si la referencia indicada es una instancia del tipo dado, o 0 si no lo es.

Nota: Dado que B siempre debe ser una referencia (y no un valor primitivo), esto siempre dará como resultado que se almacene 0 si C se refiere a un tipo primitivo.

21 12x longitud de matriz vA, vB A: registro de destino (4 bits)
B: registro portador de referencia de matriz (4 bits)
Almacene en el registro de destino dado la longitud de la matriz indicada, en entradas
22 21c vAA de instancia nueva, tipo@BBBB A: registro de destino (8 bits)
B: índice de tipo
Construya una nueva instancia del tipo indicado, almacenando una referencia a ella en el destino. El tipo debe hacer referencia a una clase que no sea de matriz.
23 22c nueva matriz vA, vB, tipo@CCCC A: registro de destino (4 bits)
B: registro de tamaño
C: índice de tipo
Construya una nueva matriz del tipo y tamaño indicados. El tipo debe ser un tipo de matriz.
24 35c lleno-nueva-matriz {vC, vD, vE, vF, vG}, type@BBBB A: tamaño de la matriz y número de palabras del argumento (4 bits)
B: índice de tipo (16 bits)
C..G: registros de argumentos (4 bits cada uno)
Construya una matriz del tipo y tamaño dados, llenándola con los contenidos proporcionados. El tipo debe ser un tipo de matriz. El contenido de la matriz debe ser de una sola palabra (es decir, no hay matrices de long o double , pero se aceptan tipos de referencia). La instancia construida se almacena como un "resultado" de la misma manera que las instrucciones de invocación del método almacenan sus resultados, por lo que la instancia construida debe moverse a un registro con una instrucción move-result-object inmediatamente posterior (si se va a utilizar ).
25 3rc lleno-nueva-matriz/rango {vCCCC .. vNNNN}, type@BBBB A: tamaño de la matriz y número de palabras del argumento (8 bits)
B: índice de tipo (16 bits)
C: primer registro de argumento (16 bits)
N = A + C - 1
Construya una matriz del tipo y tamaño dados, llenándola con los contenidos proporcionados. Las aclaraciones y restricciones son las mismas que las de filled-new-array , descritas anteriormente.
26 31t fill-array-data vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en " fill-array-data-payload Format") A: referencia de matriz (8 bits)
B: compensación de "rama" firmada a pseudoinstrucción de datos de tabla (32 bits)
Llene la matriz dada con los datos indicados. La referencia debe ser a una matriz de primitivas, y la tabla de datos debe coincidir en tipo y no debe contener más elementos de los que caben en la matriz. Es decir, la matriz puede ser más grande que la tabla, y si es así, solo se establecen los elementos iniciales de la matriz, dejando el resto solo.
27 11x tirar vaa A: registro portador de excepciones (8 bits)
Lanzar la excepción indicada.
28 10t ir a +AA A: compensación de rama firmada (8 bits) Saltar incondicionalmente a la instrucción indicada.

Nota: El desplazamiento de rama no debe ser 0 . (Un bucle giratorio puede construirse legalmente con goto/32 o incluyendo un nop como objetivo antes de la bifurcación).

29 20t ir a/16 +AAAA A: compensación de rama firmada (16 bits)
Saltar incondicionalmente a la instrucción indicada.

Nota: El desplazamiento de rama no debe ser 0 . (Un bucle giratorio puede construirse legalmente con goto/32 o incluyendo un nop como objetivo antes de la bifurcación).

2a 30t ir a/32 +AAAAAAAA A: compensación de rama firmada (32 bits)
Saltar incondicionalmente a la instrucción indicada.
2b 31t empaquetado-conmutador vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en "formato packed-switch-payload ") A: registrarse para probar
B: compensación de "rama" firmada a pseudoinstrucción de datos de tabla (32 bits)
Saltar a una nueva instrucción basada en el valor en el registro dado, utilizando una tabla de compensaciones correspondientes a cada valor en un rango integral particular, o pasar a la siguiente instrucción si no hay ninguna coincidencia.
2c 31t sparse-switch vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en "formato sparse-switch-payload ") A: registrarse para probar
B: compensación de "rama" firmada a pseudoinstrucción de datos de tabla (32 bits)
Saltar a una nueva instrucción basada en el valor en el registro dado, utilizando una tabla ordenada de pares de compensación de valores, o pasar a la siguiente instrucción si no hay ninguna coincidencia.
2d..31 23x cmp tipo vAA, vBB, vCC
2d: cml-float (sesgo lt)
2e: cmpg-float (sesgo de gt)
2f: cml-doble (sesgo lt)
30: cmpg-doble (sesgo gt)
31: cmp-largo
A: registro de destino (8 bits)
B: primer registro fuente o par
C: segundo registro fuente o par
Realice la comparación long o de punto flotante indicada, estableciendo a en 0 si b == c , 1 si b > c , o -1 si b < c . El "sesgo" enumerado para las operaciones de punto flotante indica cómo se tratan las comparaciones NaN : las instrucciones "gt bias" devuelven 1 para las comparaciones NaN , y las instrucciones "lt bias" devuelven -1 .

Por ejemplo, para comprobar si el punto flotante x < y es recomendable utilizar cmpg-float ; un resultado de -1 indica que la prueba fue verdadera y los otros valores indican que fue falsa debido a una comparación válida o porque uno de los valores fue NaN .

32..37 22t si prueba vA, vB, +CCCC
32: si-equivalente
33: si-ne
34: si-lt
35: si-ge
36: si-gt
37: si-le
A: primer registro para probar (4 bits)
B: segundo registro a probar (4 bits)
C: compensación de rama firmada (16 bits)
Ramifica al destino dado si los valores de los dos registros dados se comparan como se especifica.

Nota: El desplazamiento de rama no debe ser 0 . (Un bucle giratorio puede construirse legalmente bifurcándose alrededor de un goto hacia atrás o incluyendo un nop como objetivo antes de la bifurcación).

38..3d 21t si- prueba z vAA, +BBBB
38: si-eqz
39: si-nez
3a: si-ltz
3b: si-gez
3c: si-gtz
3d: si-lez
A: registro para probar (8 bits)
B: compensación de rama firmada (16 bits)
Ramifica al destino dado si el valor del registro dado se compara con 0 como se especifica.

Nota: El desplazamiento de rama no debe ser 0 . (Un bucle giratorio puede construirse legalmente bifurcándose alrededor de un goto hacia atrás o incluyendo un nop como objetivo antes de la bifurcación).

3e..43 10x (no usado) (no usado)
44..51 23x arrayop vAA, vBB, vCC
44: conseguir
45: toda la edad
46: objeto de edad
47: edad-booleano
48: byte de edad
49: edad-char
4a: edad corta
4b: poner
4c: aput-wide
4d: aput-objeto
4e: aput-booleano
4f: un byte de entrada
50: aput-char
51: aput-corto
A: registro de valor o par; puede ser origen o destino (8 bits)
B: registro de matriz (8 bits)
C: registro de índice (8 bits)
Realice la operación de matriz identificada en el índice identificado de la matriz dada, cargando o almacenando en el registro de valor.
52..5f 22c i instanciaop vA, vB, field@CCCC
52: entiendo
53: iget-wide
54: iget-objeto
55: iget-booleano
56: iget-byte
57: iget-char
58: me pongo corto
59: entrada
5a: en toda la entrada
5b: iput-objeto
5c: iput-booleano
5d: byte de entrada
5e: iput-char
5f: iput-corto
A: registro de valor o par; puede ser origen o destino (4 bits)
B: registro de objeto (4 bits)
C: índice de referencia de campo de instancia (16 bits)
Realice la operación de campo de instancia de objeto identificado con el campo identificado, cargando o almacenando en el registro de valor.

Nota: estos códigos de operación son candidatos razonables para la vinculación estática, alterando el argumento del campo para que sea un desplazamiento más directo.

60..6d 21c s staticop vAA, campo@BBBB
60: listo
61: ancho de banda
62: sget-objeto
63: sget-booleano
64: sget-byte
65: sget-char
66: sget-corto
67: escupir
68: sput-wide
69: sput-objeto
6a: sput-booleano
6b: byte de entrada
6c: sput-char
6d: sput-corto
A: registro de valor o par; puede ser origen o destino (8 bits)
B: índice de referencia de campo estático (16 bits)
Realice la operación de campo estático del objeto identificado con el campo estático identificado, cargándolo o almacenándolo en el registro de valor.

Nota: estos códigos de operación son candidatos razonables para la vinculación estática, alterando el argumento del campo para que sea un desplazamiento más directo.

6e..72 35c invocar tipo {vC, vD, vE, vF, vG}, meth@BBBB
6e: invocar-virtual
6f: invocar-super
70: invocar-directo
71: invocar-estática
72: interfaz de invocación
A: número de palabras del argumento (4 bits)
B: índice de referencia del método (16 bits)
C..G: registros de argumentos (4 bits cada uno)
Llame al método indicado. El resultado (si lo hay) se puede almacenar con una variante apropiada move-result* como la instrucción inmediatamente posterior.

invoke-virtual se usa para invocar un método virtual normal (un método que no es private , static o final , y tampoco es un constructor).

Cuando method_id hace referencia a un método de una clase que no es de interfaz, invoke-super se usa para invocar el método virtual de la superclase más cercana (a diferencia del que tiene el mismo method_id en la clase que llama). Se aplican las mismas restricciones de método que para invoke-virtual .

En los archivos Dex versión 037 o posterior, si method_id hace referencia a un método de interfaz, invoke-super se usa para invocar la versión más específica y no anulada de ese método definido en esa interfaz. Se aplican las mismas restricciones de método que para invoke-virtual . En archivos Dex anteriores a la versión 037 , tener una interfaz method_id es ilegal e indefinido.

invoke-direct se utiliza para invocar un método directo no static (es decir, un método de instancia que, por su naturaleza, no se puede anular, es decir, un método de instancia private o un constructor).

invoke-static se utiliza para invocar un método static (que siempre se considera un método directo).

invoke-interface se usa para invocar un método de interface , es decir, sobre un objeto cuya clase concreta no se conoce, usando un method_id que hace referencia a una interface .

Nota: estos códigos de operación son candidatos razonables para la vinculación estática, alterando el argumento del método para que sea un desplazamiento más directo (o un par de ellos).

73 10x (no usado) (no usado)
74..78 3rc invocar tipo /rango {vCCCC .. vNNNN}, meth@BBBB
74: invocar-virtual/rango
75: invocar-super/rango
76: invocar-directo/rango
77: invocar-estático/rango
78: invocar-interfaz/rango
A: número de palabras del argumento (8 bits)
B: índice de referencia del método (16 bits)
C: primer registro de argumento (16 bits)
N = A + C - 1
Llame al método indicado. Consulte la descripción del primer invoke- kind anterior para obtener detalles, advertencias y sugerencias.
79..7a 10x (no usado) (no usado)
7b..8f 12x no op vA , vB
7b: neg-int
7c: no-int
7d: neg-largo
7e: poco tiempo
7f: neg-flotante
80: neg-doble
81: de entero a largo
82: int-to-float
83: de entero a doble
84: largo a entero
85: largo para flotar
86: largo a doble
87: flotante a entero
88: flotante a largo
89: flotante a doble
8a: doble a entero
8b: doble a largo
8c: doble a flotante
8d: entero a byte
8e: int-to-char
8f: entero a corto
A: registro de destino o par (4 bits)
B: registro fuente o par (4 bits)
Realice la operación unaria identificada en el registro de origen, almacenando el resultado en el registro de destino.
90..af 23x binop vAA, vBB, vCC
90: complemento
91: sub-int
92: mu-int
93: div-int
94: remanente
95: e-int
96: o-int
97: xor-int
98: shl-int
99: shr-int
9a: ushr-int
9b: añadir-largo
9c: sublargo
9d: mul-largo
9e: div-largo
9f: rem-largo
a0: y largo
a1: o-largo
a2: xor-largo
a3: shl-largo
a4: shr-largo
a5: ushr largo
a6: añadir-flotante
a7: sub-flotador
a8: multiflotante
a9: div-flotante
aa: rem-flotante
ab: sumar-doble
ac: sub-doble
anuncio: mul-doble
ae: div-doble
af: rem-doble
A: registro de destino o par (8 bits)
B: primer registro fuente o par (8 bits)
C: segundo registro fuente o par (8 bits)
Realice la operación binaria identificada en los dos registros de origen, almacenando el resultado en el registro de destino.

Nota: A diferencia de otras operaciones matemáticas -long (que toman pares de registros para su primera y segunda fuente), shl-long , shr-long y ushr-long toman un par de registros para su primera fuente (el valor que se desplazará ), sino un solo registro para su segunda fuente (la distancia de desplazamiento).

b0..cf 12x binop /2dir va, vB
b0: complemento/2dirección
b1: subint/2dir
b2: mul-int/2dir
b3: div-int/2dir
b4: rem-int/2addr
b5: e-int/2dir
b6: o-int/2dir
b7: xor-int/2dir
b8: shl-int/2dir
b9: shr-int/2addr
ba: ushr-int/2addr
bb: add-long/2addr
bc: sub-long/2addr
bd: mul-long/2addr
ser: 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: añadir-flotante/2dirección
c7: sub-flotante/2addr
c8: mul-float/2addr
c9: div-flotador/2addr
ca: rem-float/2addr
cb: añadir-doble/2dir
cc: sub-doble/2addr
cd: mul-doble/2addr
ce: div-doble/2addr
cf: rem-doble/2dir
A: registro o par de destino y primera fuente (4 bits)
B: segundo registro fuente o par (4 bits)
Realice la operación binaria identificada en los dos registros fuente, almacenando el resultado en el primer registro fuente.

Nota: A diferencia de otras operaciones matemáticas -long/2addr (que toman pares de registros tanto para su destino/primera fuente como para su segunda fuente), shl-long/2addr , shr-long/2addr y ushr-long/2addr toman un registro par para su destino/primera fuente (el valor a cambiar), pero un solo registro para su segunda fuente (la distancia de cambio).

d0..d7 22s binop /lit16 vA, vB, #+CCCC
d0: complemento/lit16
d1: rsub-int (restar inversa)
d2: mul-int/lit16
d3: div-int/lit16
d4: rem-int/lit16
d5: e-int/lit16
d6: o-int/lit16
d7: xor-int/lit16
A: registro de destino (4 bits)
B: registro fuente (4 bits)
C: constante int con signo (16 bits)
Realiza la operación binaria indicada en el registro indicado (primer argumento) y el valor literal (segundo argumento), almacenando el resultado en el registro de destino.

Nota: rsub-int no tiene sufijo ya que esta versión es el código de operación principal de su familia. Además, consulte a continuación para obtener detalles sobre su semántica.

d8..e2 22b binop /lit8 vaA, vBB, #+CC
d8: complemento/lit8
d9: rsub-int/lit8
da: mul-int/lit8
db: div-int/lit8
corriente continua: rem-int/lit8
dd: e-int/lit8
de: o-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: shr-int/lit8
e2: ushr-int/lit8
A: registro de destino (8 bits)
B: registro fuente (8 bits)
C: constante int con signo (8 bits)
Realiza la operación binaria indicada en el registro indicado (primer argumento) y el valor literal (segundo argumento), almacenando el resultado en el registro de destino.

Nota: Consulte a continuación para obtener detalles sobre la semántica de rsub-int .

e3..f9 10x (no usado) (no usado)
fa 45cc invocar polimórfico {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: número de palabras del argumento (4 bits)
B: índice de referencia del método (16 bits)
C: receptor (4 bits)
D..G: registros de argumentos (4 bits cada uno)
H: índice de referencia del prototipo (16 bits)
Invoque el método polimórfico de firma indicado. El resultado (si lo hay) se puede almacenar con una variante apropiada move-result* como la instrucción inmediatamente posterior.

La referencia del método debe ser un método polimórfico de firma, como java.lang.invoke.MethodHandle.invoke o java.lang.invoke.MethodHandle.invokeExact .

El receptor debe ser un objeto compatible con el método polimórfico de firma que se invoca.

La referencia del prototipo describe los tipos de argumento proporcionados y el tipo de retorno esperado.

El invoke-polymorphic puede generar excepciones cuando se ejecuta. Las excepciones se describen en la documentación de la API para el método polimórfico de firma que se invoca.

Presente en archivos Dex desde la versión 038 en adelante.
fb 4rcc invocar-polimórfico/rango {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: número de palabras del argumento (8 bits)
B: índice de referencia del método (16 bits)
C: receptor (16 bits)
H: índice de referencia del prototipo (16 bits)
N = A + C - 1
Invoque el identificador de método indicado. Consulte la descripción invoke-polymorphic anterior para obtener más detalles.

Presente en archivos Dex desde la versión 038 en adelante.
fc35c invocar-personalizado {vC, vD, vE, vF, vG}, call_site@BBBB A: número de palabras del argumento (4 bits)
B: índice de referencia del sitio de la llamada (16 bits)
C..G: registros de argumentos (4 bits cada uno)
Resuelve e invoca el sitio de llamada indicado. El resultado de la invocación (si lo hay) puede almacenarse con una variante move-result* apropiada como la instrucción inmediatamente posterior.

Esta instrucción se ejecuta en dos fases: resolución del sitio de llamada e invocación del sitio de llamada.

La resolución del sitio de llamadas verifica si el sitio de llamadas indicado tiene una instancia java.lang.invoke.CallSite asociada. De lo contrario, se invoca el método del enlazador de arranque para el sitio de llamada indicado utilizando los argumentos presentes en el archivo DEX (consulte call_site_item ). El método del enlazador bootstrap devuelve una instancia de java.lang.invoke.CallSite que luego se asociará con el sitio de llamada indicado si no existe ninguna asociación. Es posible que otro subproceso ya haya realizado la asociación primero y, de ser así, la ejecución de la instrucción continúa con la primera instancia asociada de java.lang.invoke.CallSite .

La invocación del sitio de llamada se realiza en el destino java.lang.invoke.MethodHandle de la instancia java.lang.invoke.CallSite resuelta. El objetivo se invoca como si se ejecutara invoke-polymorphic (descrito anteriormente) utilizando el controlador de método y los argumentos de la instrucción invoke-custom como argumentos para una invocación de controlador de método exacto.

Las excepciones generadas por el método del enlazador de arranque se incluyen en un java.lang.BootstrapMethodError . También se genera un BootstrapMethodError si:
  • el método del enlazador bootstrap no puede devolver una instancia java.lang.invoke.CallSite .
  • el java.lang.invoke.CallSite devuelto tiene un destino de identificador de método null .
  • el destino del identificador del método no es del tipo solicitado.
Presente en archivos Dex desde la versión 038 en adelante.
fd3rc invocar-personalizado/rango {vCCCC .. vNNNN}, call_site@BBBB A: número de palabras del argumento (8 bits)
B: índice de referencia del sitio de la llamada (16 bits)
C: primer registro de argumento (16 bits)
N = A + C - 1
Resolver e invocar un sitio de llamada. Consulte la descripción invoke-custom anterior para obtener más detalles.

Presente en archivos Dex desde la versión 038 en adelante.
fe 21c manejo-método-const vAA, manejo_método@BBBB A: registro de destino (8 bits)
B: índice de identificador de método (16 bits)
Mueva una referencia al identificador de método especificado por el índice dado en el registro especificado.

Presente en archivos Dex desde la versión 039 en adelante.
ff 21c const-método-tipo vAA, proto@BBBB A: registro de destino (8 bits)
B: referencia del prototipo del método (16 bits)
Mueve una referencia al prototipo del método especificado por el índice dado al registro especificado.

Presente en archivos Dex desde la versión 039 en adelante.

formato de carga útil de conmutación empaquetada

Nombre Formato Descripción
identificador ucorto = 0x0100 identificar pseudo-opcode
Talla corto número de entradas en la tabla
primera_clave En t primer (y más bajo) valor de la caja del interruptor
objetivos En t[] lista de objetivos de rama relativos al size . Los objetivos son relativos a la dirección del código de operación del interruptor, no de esta tabla.

Nota: El número total de unidades de código para una instancia de esta tabla es (size * 2) + 4 .

formato de carga útil de conmutador disperso

Nombre Formato Descripción
identificador ucorto = 0x0200 identificar pseudo-opcode
Talla corto número de entradas en la tabla
llaves En t[] lista de valores clave de size , ordenados de menor a mayor
objetivos En t[] lista de objetivos de rama relativos al size , cada uno correspondiente al valor clave en el mismo índice. Los objetivos son relativos a la dirección del código de operación del interruptor, no de esta tabla.

Nota: El número total de unidades de código para una instancia de esta tabla es (size * 4) + 2 .

formato de carga útil de datos de matriz de relleno

Nombre Formato Descripción
identificador ucorto = 0x0300 identificar pseudo-opcode
ancho_elemento corto número de bytes en cada elemento
Talla uint número de elementos en la tabla
datos ubyte[] valores de datos

Nota: El número total de unidades de código para una instancia de esta tabla es (size * element_width + 1) / 2 + 4 .

Detalles de la operación matemática

Nota: Las operaciones de coma flotante deben seguir las reglas de IEEE 754, utilizando el subdesbordamiento gradual y de redondeo al más cercano, excepto donde se indique lo contrario.

código de operación C semántica notas
negativo int32a;
int32 resultado = -a;
Complemento a dos unario.
no-int int32a;
int32 resultado = ~a;
Unos-complemento unario.
neg-largo int64a;
int64 resultado = -a;
Complemento a dos unario.
No largo int64a;
int64 resultado = ~a;
Unos-complemento unario.
neg-flotante flotar un;
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 .