Formato de código de bytes de Dalvik

Diseño general

  • El modelo de máquina y las convenciones de llamada pretenden imitar aproximadamente arquitecturas reales comunes y convenciones de llamada de estilo C:
    • La máquina se basa en registros y el tamaño de los fotogramas se fija en el momento de su creación. Cada cuadro consta de un número particular de registros (especificados por el método), así como de cualquier dato adjunto necesario para ejecutar el método, como (pero no limitado a) 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 existe ningún requisito de alineación para los pares de registros.
    • Cuando se utilizan para referencias de objetos, los registros se consideran lo suficientemente anchos 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 amplios consumen dos registros. A los métodos de instancia se les pasa this referencia como 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 registros de 32 bits sin interpretación no tienen que especificar si mueven enteros o flotantes.
  • Hay grupos de constantes indexados y enumerados 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 necesitar más de ocho registros es razonablemente común, muchas instrucciones se limitan a abordar solo los primeros 16 registros. Cuando sea razonablemente posible, las instrucciones permiten referencias hasta a los primeros 256 registros. Además, algunas instrucciones tienen variantes que permiten recuentos de registros mucho mayores, incluido un par de instrucciones move generales que pueden abordar registros en el rango v0v65535 . En los casos en los 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 un registro alto. registrarse (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 regulares (por ejemplo, fill-array-data ). Este tipo de instrucciones nunca deben encontrarse durante el flujo normal de ejecución. Además, las instrucciones deben ubicarse en desplazamientos de códigos de bytes pares (es decir, alineados con 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 elijan emitir estas instrucciones al final de los métodos, ya que de lo contrario probablemente se necesitarían instrucciones adicionales para ramificarlas.
  • Cuando se instala en un sistema en ejecución, algunas instrucciones pueden modificarse, cambiando su formato, como una optimización de enlaces estáticos durante 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 conocer las variantes sugeridas. La palabra "sugerido" se utiliza deliberadamente; no es obligatorio implementarlos.
  • Sintaxis humana y mnemónicos:
    • Orden de destino y luego origen para los argumentos.
    • Algunos códigos de operación tienen un sufijo de nombre desambiguante 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 de tipo tienen el sufijo de su tipo (o una abreviatura sencilla), uno de: -boolean -byte -char -short -int -long -float -double -object -string -class -void .
    • Algunos códigos de operación tienen un sufijo desambiguante para distinguir operaciones idénticas que tienen diferentes diseños u opciones de instrucciones. Estos sufijos están separados de los nombres principales con una barra diagonal (" / ") y existen principalmente para hacer 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 con 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 (implícito en 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 fuente, que debe estar en el rango v0v65535 .
  • Consulte el documento de formatos de instrucciones para obtener más detalles sobre los distintos formatos de instrucciones (enumerados en "Op. y formato"), 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

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

Nota: Las pseudoinstrucciones que contienen datos están etiquetadas 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 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 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 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 objeto a otro.
04 12x movimiento amplio vA, vB A: par de registros de destino (4 bits)
B: par de registros fuente (4 bits)
Mueva 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 disponer que ambas mitades de un par de registros se lean antes de escribir algo.

05 22x mover-ancho/desde16 vAA, vBBBB A: par de registros de destino (8 bits)
B: par de registros fuente (16 bits)
Mueva 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)
Mueva 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-movimiento vAA A: registro de destino (8 bits) Mueva el resultado de una sola palabra que no sea objeto 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 (de una sola palabra, sin objeto) no debe ignorarse; en cualquier otro lugar no es válido.
0b 11x mover-resultado-todo vAA A: par de registros de destino (8 bits) Mueva el resultado de doble palabra 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; en cualquier otro lugar no es válido.
0c 11x mover-resultado-objeto vAA A: registro de destino (8 bits) Mueva el resultado del objeto del invoke- kind más reciente al registro indicado. Esto debe hacerse como la instrucción inmediatamente después de una invoke- kind o filled-new-array cuyo resultado (objeto) no debe ignorarse; en cualquier otro lugar no es válido.
0d 11x excepción de movimiento vAA A: registro de destino (8 bits) Guarde una excepción recién detectada en el registro proporcionado. Esta debe ser la primera instrucción de cualquier manejador de excepciones cuya excepción detectada no deba ignorarse, y esta instrucción solo debe ocurrir como la primera instrucción de un manejador de excepciones; en cualquier otro lugar no es válido.
0e 10x retorno nulo Regreso de un método void .
0f 11x devolver vaa A: registro de valor de retorno (8 bits) Retorno desde un método de devolución de valor sin objeto de ancho único (32 bits).
10 11x vAA de todo el retorno A: valor de retorno par de registros (8 bits) Regreso de un método de devolución de valor de doble ancho (64 bits).
11 11x objeto de retorno vAA A: registro de valor de retorno (8 bits) Regreso de un método de devolución de objetos.
12 11n constante/4vA, #+B A: registro de destino (4 bits)
B: int con signo (4 bits)
Mueva el valor literal dado (signo extendido a 32 bits) al registro especificado.
13 21 constante/16 vAA, #+BBBB A: registro de destino (8 bits)
B: int con signo (16 bits)
Mueva el valor literal dado (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
Mueva el valor literal dado al registro especificado.
15 21h constante/alto16 vAA, #+BBBB0000 A: registro de destino (8 bits)
B: int con signo (16 bits)
Mueva el valor literal dado (cero a la derecha extendido a 32 bits) al registro especificado.
16 21 ancho constante/16 vAA, #+BBBB A: registro de destino (8 bits)
B: int con signo (16 bits)
Mueva el valor literal dado (signo extendido a 64 bits) al par de registros especificado.
17 31i ancho constante/32 vAA, #+BBBBBBBB A: registro de destino (8 bits)
B: int con signo (32 bits)
Mueva el valor literal dado (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 constante ancho/alto16 vAA, #+BBBB000000000000 A: registro de destino (8 bits)
B: int con signo (16 bits)
Mueva el valor literal dado (cero a la derecha extendido a 64 bits) al par de registros especificado.
1a 21c cadena constante vAA, cadena@BBBB A: registro de destino (8 bits)
B: índice de cadena
Mueva una referencia a la cadena especificada por el índice dado al registro especificado.
1b 31c cadena constante/vAA jumbo, cadena@BBBBBBBB A: registro de destino (8 bits)
B: índice de cadena
Mueva una referencia a la cadena especificada por el índice dado al registro especificado.
1c 21c clase constante vAA, tipo@BBBB A: registro de destino (8 bits)
B: índice de tipo
Mueva una referencia a la clase especificada por el índice dado al registro especificado. En el caso de que el tipo indicado sea primitivo, esto almacenará una referencia a la clase degenerada del tipo primitivo.
1d 11x monitor-ingrese vAA A: registro de referencia (8 bits) Adquirir el monitor para el objeto indicado.
1e 11x monitor-salida vAA A: registro de referencia (8 bits) Suelte el monitor para el objeto indicado.

Nota: Si esta instrucción necesita generar una excepción, debe hacerlo como si la computadora ya hubiera avanzado más allá de la instrucción. Puede ser útil pensar en esto como si la instrucción se ejecutara exitosamente (en cierto sentido) y la excepción se lanzara 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 utilice un bloque general de limpieza de monitor (por ejemplo, finally ) como limpieza de monitor para ese bloque en sí, como una forma de manejar las excepciones arbitrarias que podrían generarse debido a la implementación histórica de Thread.stop() . Thread.stop() , sin dejar de lograr tener una higiene adecuada del monitor.

1f 21c check-cast vAA, escriba @BBBB A: registro de referencia (8 bits)
B: índice de tipo (16 bits)
Lanza 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 hace referencia a un tipo primitivo.

20 22c instancia de vA, vB, tipo@CCCC A: registro de destino (4 bits)
B: registro 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 en caso contrario.

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

21 12x longitud de la matriz vA, vB A: registro de destino (4 bits)
B: registro de referencia de matriz (4 bits)
Almacenar en el registro de destino dado la longitud de la matriz indicada, en entradas
22 21c vAA de nueva instancia, 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 una 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 nueva matriz llena {vC, vD, vE, vF, vG}, tipo@BBBB A: tamaño de la matriz y recuento de palabras de 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 el contenido proporcionado. 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 tipo long o double , pero los tipos de referencia son aceptables). 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 3c nueva matriz llena/rango {vCCCC .. vNNNN}, tipo@BBBB A: tamaño de la matriz y recuento de palabras de argumento (8 bits)
B: índice de tipo (16 bits)
C: registro del primer argumento (16 bits)
N = A + C - 1
Construya una matriz del tipo y tamaño dados, llenándola con el contenido proporcionado. Las aclaraciones y restricciones son las mismas que las filled-new-array descritas anteriormente.
26 31t fill-array-data vAA, +BBBBBBBB (con datos suplementarios como se especifica a continuación en "Formato fill-array-data-payload ") A: referencia de matriz (8 bits)
B: pseudoinstrucción de desplazamiento de "rama" firmada a los datos de la tabla (32 bits)
Complete 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, de ser 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)
Lanza la excepción indicada.
28 10t ir a +AA A: desplazamiento de rama con signo (8 bits) Saltar incondicionalmente a la instrucción indicada.

Nota: El desplazamiento de la rama no debe ser 0 . (Se puede construir legalmente un bucle de giro con goto/32 o incluyendo un nop como objetivo antes de la rama).

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

Nota: El desplazamiento de la rama no debe ser 0 . (Se puede construir legalmente un bucle de giro con goto/32 o incluyendo un nop como objetivo antes de la rama).

2a 30t ir a/32 +AAAAAAAA A: desplazamiento de rama con signo (32 bits)
Saltar incondicionalmente a la instrucción indicada.
2b 31t pack-switch-vAA, +BBBBBBBB (con datos suplementarios como se especifica a continuación en "Formato packed-switch-payload ") A: registrarse para probar
B: pseudoinstrucción de desplazamiento de "rama" firmada a los datos de la tabla (32 bits)
Salte a una nueva instrucción basada en el valor en el registro dado, usando una tabla de compensaciones correspondientes a cada valor en un rango integral particular, o pase a la siguiente instrucción si no hay 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: pseudoinstrucción de desplazamiento de "rama" firmada a los datos de la tabla (32 bits)
Salte a una nueva instrucción basada en el valor del registro dado, utilizando una tabla ordenada de pares de valores-compensaciones, o pase a la siguiente instrucción si no hay coincidencia.
2d..31 23x cmp tipo vAA, vBB, vCC
2d: cmmpl-float (sesgo lt)
2e: cmpg-float (sesgo gt)
2f: cmpl-doble (sesgo lt)
30: cmpg-doble (sesgo gt)
31: cmp-largo
A: registro de destino (8 bits)
B: primer registro o par fuente
C: segundo registro o par fuente
Realice el punto flotante indicado o una comparación long , 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 sesgo" devuelven 1 para comparaciones NaN y las instrucciones "lt sesgo" 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 era NaN .

32..37 22t si- prueba vA, vB, +CCCC
32: si-eq
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 para probar (4 bits)
C: desplazamiento de rama con signo (16 bits)
Vaya al destino dado si los valores de los dos registros dados se comparan según lo especificado.

Nota: El desplazamiento de la rama no debe ser 0 . (Un bucle de giro 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: registrarse para probar (8 bits)
B: desplazamiento de rama con signo (16 bits)
Salte al destino dado si el valor del registro dado se compara con 0 como se especifica.

Nota: El desplazamiento de la rama no debe ser 0 . (Un bucle de giro 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-objeto
47: aget-booleano
48: aget-byte
49: aget-char
4a: get-short
4b: aput
4c: todo el aput
4d: objeto-aput
4e: aput-booleano
4f: aput-byte
50: aput-char
51: aput-corto
A: registro o par de valores; puede ser origen o destino (8 bits)
B: registro de matriz (8 bits)
C: registro índice (8 bits)
Realice la operación de matriz identificada en el índice identificado de la matriz dada, cargándola o almacenándola en el registro de valor.
52..5f 22c i instanciaop vA, vB, campo@CCCC
52: conseguir
53: iget-ancho
54: iget-objeto
55: iget-booleano
56: iget-byte
57: iget-char
58: iget-corto
59: entrada
5a: en toda la entrada
5b: objeto-iput
5c: iput-booleano
5d: byte de entrada
5e: iput-char
5f: iput-corto
A: registro o par de valores; puede ser origen o destino (4 bits)
B: registro de objeto (4 bits)
C: índice de referencia del campo de instancia (16 bits)
Realice la operación de campo de instancia de objeto identificado con el campo identificado, cargándolo o almacenándolo en el registro de valor.

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

60..6d 21c s staticop vAA, campo@BBBB
60: sget
61: todo el sget
62: objeto-sget
63: sget-booleano
64: sget-byte
65: sget-char
66: sget-corto
67: escupir
68: todo el sput
69: objeto de esputo
6a: sput-booleano
6b: byte de salida
6c: sput-char
6d: sput-corto
A: registro o par de valores; puede ser origen o destino (8 bits)
B: índice de referencia de campo estático (16 bits)
Realice la operación del 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 enlaces estáticos, alterando el argumento del campo para que sea un desplazamiento más directo.

6e..72 35c invocar tipo {vC, vD, vE, vF, vG}, meta@BBBB
6e: invocar-virtual
6f: invocar-super
70: invocación directa
71: invocar-estático
72: interfaz de invocación
A: recuento de palabras de 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 instrucción inmediatamente posterior.

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

Cuando el 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 se refiere 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 y no está definido.

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 interface , es decir, en 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}, meta@BBBB
74: invocar-virtual/rango
75: invocar-super/rango
76: invocación directa/rango
77: invocar-estático/rango
78: invocar-interfaz/rango
A: recuento de palabras de argumento (8 bits)
B: índice de referencia del método (16 bits)
C: registro del primer argumento (16 bits)
N = A + C - 1
Llame al método indicado. Consulte la descripción anterior del primer invoke- kind para obtener detalles, advertencias y sugerencias.
79..7a 10x (no usado) (no usado)
7b..8f 12x unop va, vB
7b: neg-int
7c: no-int
7d: neg-largo
7e: no mucho
7f: flotación negativa
80: neg-doble
81: int a largo
82: int-a-flotar
83: int-a-doble
84: largo a int
85: largo para flotar
86: largo a doble
87: flotante a int
88: flotante a largo
89: flotar a doble
8a: doble a int
8b: doble a largo
8c: doble para flotar
8d: int a byte
8e: int-a-char
8f: int a corto
A: registro o par de destino (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: multiint
93: div-int
94: remanente
95: y-int
96: o-int
97: xor-int
98: shl-int
99: encogimiento
9a: ushr-int
9b: complemento 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: agregar flotación
a7: subflotación
a8: mul-flotación
a9: div-flotante
aa: flotación remota
ab: sumar-doble
ac: subdoble
anuncio: mul-doble
ae: div-doble
af: rem-doble
A: registro o par de destino (8 bits)
B: primer registro o par fuente (8 bits)
C: segundo registro o par fuente (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 tanto para su primera como para su segunda fuente), shl-long , shr-long y ushr-long toman un par de registros para su primera fuente (el valor que se va a desplazar). ), sino un solo registro para su segunda fuente (la distancia de desplazamiento).

b0..cf 12x binop /2dirección vA, vB
b0: complemento/2dirección
b1: sub-int/2dirección
b2: mul-int/2addr
b3: div-int/2dirección
b4: rem-int/2addr
b5: and-int/2addr
b6: o-int/2addr
b7: xor-int/2dirección
b8: shl-int/2addr
b9: shr-int/2addr
ba: ushr-int/2addr
bb: agregar largo/2dirección
bc: sublargo/2addr
bd: mul-long/2addr
ser: div-long/2addr
novio: rem-long/2addr
c0: y-largo/2addr
c1: o-largo/2dirección
c2: xor-long/2addr
c3: shl-long/2addr
c4: shr-long/2addr
c5: ushr-long/2addr
c6: agregar-flotante/2addr
c7: subflotación/2dirección
c8: mul-flotante/2addr
c9: div-float/2addr
ca: rem-float/2addr
cb: agregar-doble/2dirección
cc: subdoble/2addr
cd: mul-doble/2addr
ce: div-doble/2addr
cf: rem-doble/2addr
A: registro o par de destino y primer origen (4 bits)
B: segundo registro o par fuente (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 que se va a desplazar), pero un único registro para su segunda fuente (la distancia de desplazamiento).

d0..d7 22s binop /lit16 vA, vB, #+CCCC
d0: complemento/lit16
d1: rsub-int (resta inversa)
d2: mul-int/lit16
d3: div-int/lit16
d4: remanente/lit16
d5: and-int/lit16
d6: or-int/lit16
d7: xor-int/lit16
A: registro de destino (4 bits)
B: registro fuente (4 bits)
C: constante int con signo (16 bits)
Realizar la operación binaria indicada sobre 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
base de datos: div-int/lit8
CC: 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: registro de destino (8 bits)
B: registro fuente (8 bits)
C: constante int con signo (8 bits)
Realizar la operación binaria indicada sobre 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)
45cc invocar polimórfico {vC, vD, vE, vF, vG}, meta@BBBB, proto@HHHH A: recuento de palabras de 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)
Invoca el método polimórfico de firma indicado. El resultado (si lo hay) se puede almacenar con una variante apropiada move-result* como instrucción inmediatamente posterior.

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

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

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

El código de bytes 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.
facebook 4rcc invocar-polimórfico/rango {vCCCC .. vNNNN}, meta@BBBB, proto@HHHH A: recuento de palabras de 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
Invoca el identificador del 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.
fc 35c invocar-personalizado {vC, vD, vE, vF, vG}, call_site@BBBB A: recuento de palabras de argumento (4 bits)
B: índice de referencia del sitio de 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 existe) se puede almacenar con una variante apropiada move-result* como 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 comprueba si el sitio de llamadas indicado tiene una instancia java.lang.invoke.CallSite asociada. De lo contrario, el método del vinculador de arranque para el sitio de llamada indicado se invoca utilizando argumentos presentes en el archivo DEX (consulte call_site_item ). El método del vinculador bootstrap devuelve una instancia 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 java.lang.invoke.CallSite asociada.

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 estuviera ejecutando invoke-polymorphic (descrito anteriormente) utilizando el identificador del método y los argumentos de la instrucción invoke-custom como argumentos para una invocación exacta del identificador de método.

Las excepciones generadas por el método del vinculador bootstrap están envueltas en un java.lang.BootstrapMethodError . También se genera un BootstrapMethodError si:
  • el método del vinculador de arranque no puede devolver una instancia java.lang.invoke.CallSite .
  • el java.lang.invoke.CallSite devuelto tiene un objetivo de identificador de método null .
  • el objetivo 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: recuento de palabras de argumento (8 bits)
B: índice de referencia del sitio de llamada (16 bits)
C: registro del primer 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 mango-método-const vAA, mango_método@BBBB A: registro de destino (8 bits)
B: índice de identificador de método (16 bits)
Mueva una referencia al identificador del método especificado por el índice dado al registro especificado.

Presente en archivos Dex desde la versión 039 en adelante.
ff 21c método constante tipo vAA, proto@BBBB A: registro de destino (8 bits)
B: referencia del prototipo del método (16 bits)
Mueva 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 del conmutador empaquetado

Nombre Formato Descripción
identificador ucorto = 0x0100 identificar pseudocódigo de operación
tamaño corto número de entradas en la tabla
primera_clave En t primer (y más bajo) valor del caso de cambio
objetivos En t[] lista de objetivos de rama relativos size . Los objetivos son relativos a la dirección del código de operación del conmutador, no a 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 cambio disperso

Nombre Formato Descripción
identificador ucorto = 0x0200 identificar pseudocódigo de operación
tamaño corto número de entradas en la tabla
llaves En t[] lista de valores clave size , ordenados de menor a mayor
objetivos En t[] lista de objetivos de rama relativos 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 conmutador, no a 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 pseudocódigo de operación
ancho_elemento corto número de bytes en cada elemento
tamaño 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 IEEE 754, utilizando redondeo al más cercano y desbordamiento gradual, excepto que se indique lo contrario.

Código de operación C Semántica Notas
neg-int int32a;
resultado int32 = -a;
Complemento unario a dos.
no-int int32a;
resultado int32 = ~a;
Complemento unario.
neg-largo int64a;
resultado int64 = -a;
Complemento unario a dos.
No largo int64a;
resultado int64 = ~a;
Complemento unario.
flotación negativa flotar un;
resultado flotante = -a;
Negación de coma flotante.
neg-doble doble a;
resultado doble = -a;
Negación de coma flotante.
int a largo int32a;
resultado int64 = (int64) a;
Firme la extensión de int32 en int64 .
int-a-flotar int32a;
resultado flotante = (flotante) a;
Conversión de int32 a float , usando redondear. Esto pierde precisión para algunos valores.
int-doblar int32 a;
resultado doble = (doble) a;
Conversión de int32 a double .
largo int64 a;
int32 resultado = (int32) a;
Truncamiento de int64 en int32 .
largo int64 a;
resultado flotante = (flotante) a;
Conversión de int64 a float , usando redondear. Esto pierde precisión para algunos valores.
largo int64 a;
resultado doble = (doble) a;
Conversión de int64 a double , usando redondear a la más reina. Esto pierde precisión para algunos valores.
flotante flotar un;
int32 resultado = (int32) a;
Conversión de float a int32 , usando el-cero redondo de cero. NaN y -0.0 (cero negativo) se convierten al entero 0 . Los infinitos y los valores con una magnitud demasiado grande para representarse se convierten en 0x7fffffff o -0x80000000 dependiendo del signo.
flotante flotar un;
int64 resultado = (int64) a;
Conversión de float a int64 , usando el cero redondo de cero. Las mismas reglas de caso especial que para float-to-int se aplican aquí, excepto que los valores fuera de rango se convierten en 0x7fffffffffffffff o -0x8000000000000000 dependiendo del signo.
flotante a doble flotar un;
resultado doble = (doble) a;
Conversión de float a double , preservando el valor exactamente.
doble doble a;
int32 resultado = (int32) a;
Conversión de double a int32 , utilizando cero redondo de cero. Las mismas reglas de casos especiales que para float-to-int se aplican aquí.
doble doble a;
int64 resultado = (int64) a;
Conversión de double a int64 , utilizando cero redondo de cero. Las mismas reglas especiales de caso que para float-to-long se aplican aquí.
doble a piso doble a;
resultado flotante = (flotante) a;
Conversión de double a float , usando redondear. Esto pierde precisión para algunos valores.
int-byte int32 a;
int32 result = (a << 24) >> 24;
Truncamiento de int32 a int8 , signo extendiendo el resultado.
int-to-Char int32 a;
int32 result = a & 0xffff;
Truncamiento de int32 a uint16 , sin extensión de signo.
int-a-short int32 a;
int32 result = (a << 16) >> 16;
Truncamiento de int32 a int16 , signo que extiende el resultado.
complemento int32 a, b;
int32 resultado = a + b;
Adición de Twos-Complemento.
submarino int32 a, b;
int32 resultado = a - b;
RESTRACIÓN DE TWOS-COMPLEMENT.
intensidad int32 a, b;
int32 resultado = b - a;
RESTRACCIÓN INVERSE DE TWOS-COMPLEMENT.
insignificante int32 a, b;
int32 resultado = a * b;
Multiplicación de Twos-Complement.
div-entrada int32 a, b;
Resultado int32 = a / b;
División de complemento de dos, redondeada hacia cero (es decir, truncada a entero). Esto arroja ArithmeticException si b == 0 .
rem-intento int32 a, b;
int32 resultado = a % b;
DWOS-COMPLEMENTE RESTERENTE CUENTA DIVISIÓN. El signo del resultado es el mismo que el de a , y se define con mayor precisión como result == a - (a / b) * b Esto arroja ArithmeticException si b == 0 .
y int32 a, b;
int32 resultado = a & b;
Bit a bit Y.
o-entrada int32 a, b;
int32 resultado = a | b;
O bit a bit.
xor int32 a, b;
int32 resultado = a ^ b;
Bitwise xor.
SHL-INT int32 a, b;
int32 result = a << (b & 0x1f);
Cambio de bit a bit a la izquierda (con argumento enmascarado).
shr-intemperatura int32 a, b;
int32 resultado = a >> (b & 0x1f);
Bitwise firmado desplazamiento a la derecha (con argumento enmascarado).
USHR-INT uint32 a, b;
int32 resultado = a >> (b & 0x1f);
Bitwise Unsigned Shift Derecha (con argumento enmascarado).
anhelo int64 a, b;
int64 resultado = a + b;
Adición de Twos-Complemento.
subterráneo int64 a, b;
int64 resultado = a - b;
RESTRACIÓN DE TWOS-COMPLEMENT.
mul int64 a, b;
int64 resultado = a * b;
Multiplicación de Twos-Complement.
Div-Div int64 a, b;
Resultado int64 = a / b;
División de complemento de dos, redondeada hacia cero (es decir, truncada a entero). Esto arroja ArithmeticException si b == 0 .
remulgado int64 a, b;
int64 resultado = a % b;
DWOS-COMPLEMENTE RESTERENTE CUENTA DIVISIÓN. El signo del resultado es el mismo que el de a , y se define con mayor precisión como result == a - (a / b) * b Esto arroja ArithmeticException si b == 0 .
y largo int64 a, b;
int64 resultado = a & b;
Bit a bit Y.
o largo int64 a, b;
int64 resultado = a | b;
O bit a bit.
anual int64 a, b;
int64 resultado = a ^ b;
Bitwise xor.
shl largo int64 a;
int32 b;
int64 resultado = a << (b & 0x3f);
Cambio de bit a bit a la izquierda (con argumento enmascarado).
shr largo int64 a;
int32 b;
int64 resultado = a >> (b & 0x3f);
Bitwise firmado desplazamiento a la derecha (con argumento enmascarado).
USHR largo uint64 a;
int32 b;
int64 resultado = a >> (b & 0x3f);
Bitwise Unsigned Shift Derecha (con argumento enmascarado).
agrega flotar A, B;
resultado flotante = a + b;
Adición de punto flotante.
subsuelo flotar A, B;
Resultado flotante = a - b;
RESTRACIÓN DEL PUNTO FLOTANTE.
mul-float flotar A, B;
resultado flotante = a * b;
Multiplicación del punto flotante.
Divlibre flotar A, B;
resultado flotante = a / b;
División de puntos flotantes.
remo flotar A, B;
resultado flotante = a % b;
Punto flotante RESTANTE ASPARACIÓN AL DIVISIÓN. Esta función es diferente al resto IEEE 754 y se define como result == a - roundTowardZero(a / b) * b .
agrega-doble doble a, b;
resultado doble = a + b;
Adición de punto flotante.
subdobilar doble a, b;
resultado doble = a - b;
RESTRACIÓN DEL PUNTO FLOTANTE.
MUL-Double doble a, b;
resultado doble = a * b;
Multiplicación del punto flotante.
Div-Double doble a, b;
resultado doble = a / b;
División de puntos flotantes.
remo doble a, b;
resultado doble = A % B;
Punto flotante RESTANTE ASPARACIÓN AL DIVISIÓN. Esta función es diferente al resto IEEE 754 y se define como result == a - roundTowardZero(a / b) * b .