Diseño general
- El modelo de máquina y las convenciones de llamadas están diseñados para imitar de forma aproximada las arquitecturas reales comunes y las convenciones de llamadas de estilo C:
- La máquina se basa en registros, y los fotogramas tienen un tamaño fijo cuando se crean.
Cada marco consta de una cantidad particular de registros (especificados por el método), así como cualquier dato complementario necesario para ejecutar el método, como (sin limitaciones) el contador de programas y una referencia al archivo
.dex
que contiene el método. - Cuando se usan para valores de bits (como números enteros y de punto flotante), los registros se consideran de 32 bits de ancho. Los pares de registros adyacentes se usan para valores de 64 bits. No hay requisitos de alineación para los pares de registros.
- Cuando se usan para referencias de objetos, los registros se consideran lo suficientemente amplios como para contener exactamente una de esas referencias.
- En términos de representación por bits,
(Object) null == (int) 0
. - Los argumentos N de un método se ubican en los últimos N registros del marco de invocación del método, en orden. Los argumentos anchos consumen dos registros. A los métodos de instancia se les pasa una referencia
this
como primer argumento.
- La máquina se basa en registros, y los fotogramas tienen un tamaño fijo cuando se crean.
Cada marco consta de una cantidad particular de registros (especificados por el método), así como cualquier dato complementario necesario para ejecutar el método, como (sin limitaciones) el contador de programas y una referencia al archivo
- La unidad de almacenamiento en el flujo de instrucciones es una cantidad de 16 bits sin firmar. Algunos bits de algunas instrucciones se ignoran o deben ser cero.
- Las instrucciones no se limitan de forma gratuita a un tipo en particular. Por ejemplo, las instrucciones que mueven valores de registro de 32 bits sin interpretación no tienen que especificar si están moviendo números enteros o de punto flotante.
- Existen grupos de constantes enumerados e indexados por separado para las referencias a cadenas, tipos, campos y métodos.
- Los datos literales de bits se representan intercalados 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 a que necesitar más de ocho registros es bastante común, muchas instrucciones se limitan a abordar solo los primeros 16 registros. Cuando sea razonablemente posible, las instrucciones permiten referencias a 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
move
generales que pueden abordar registros en el rangov0
av65535
. En los casos en que no haya una variante de instrucción 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) o de un registro de resultado bajo a un registro alto (después de la operación). - Hay varias “pseudoinstrucciones” que se usan para contener cargas útiles de datos de longitud variable, a las que se hace referencia con instrucciones normales (por ejemplo,
fill-array-data
). Nunca se deben encontrar tales instrucciones durante el flujo normal de ejecución. Además, las instrucciones deben ubicarse en offsets de código de bytes con números pares (es decir, alineados con 4 bytes). Para cumplir con este requisito, las herramientas de generación de dex deben emitir una instrucciónnop
adicional como espaciador si, de otro modo, esa instrucción no estaría alineada. Por último, 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, es probable que se necesiten instrucciones adicionales para ramificarse alrededor de ellas. - Cuando se instalan en un sistema en ejecución, es posible que se alteren algunas instrucciones y cambie su formato, como una optimización de vinculación estática en el tiempo de instalación. Esto permite una ejecución más rápida una vez que se conoce la vinculación. Consulta el documento de formatos de instrucciones asociado para ver las variantes sugeridas. La palabra "sugerido" se usa con cautela, ya que no es obligatorio implementarlos.
- Sintaxis y mnemotecnias humanas:
- Orden de destino y, luego, fuente para los argumentos.
- Algunos opcodes tienen un sufijo de nombre para desambiguar que indica los tipos en los que operan:
- Los opcodes de 32 bits de tipo general no están marcados.
- Los opcodes de 64 bits de tipo general tienen el sufijo
-wide
. - Los opcodes específicos de tipo tienen el sufijo de su tipo (o una sigla directa), una de las siguientes:
-boolean
,-byte
,-char
,-short
,-int
,-long
,-float
,-double
,-object
,-string
,-class
o-void
.
- Algunos opcodes tienen un sufijo para desambiguar que distingue operaciones idénticas que tienen diferentes diseños de instrucciones o opciones. Estos sufijos se separan de los nombres principales con una barra diagonal ("
/
") y, en general, existen para que haya una asignación uno a uno con constantes estáticas en el código que genera e interpreta ejecutables (es decir, para reducir la ambigüedad para las personas). - En las descripciones que se incluyen aquí, el ancho de un valor (que indica, p.ej., el rango de una constante o la cantidad de registros a los que se puede dirigir) se enfatiza con 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 básica (mover el valor de un registro). - "
wide
" es el sufijo del nombre, que indica que opera en datos amplios (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 (que se implica en la operación; una vez más, la regla es que los argumentos de destino siempre son los primeros), que debe estar en el rangov0
av255
. - “
vBBBB
” es el registro de origen, que debe estar en el rangov0
av65535
.
- "
- Consulta el documento sobre los formatos de instrucción para obtener más detalles sobre los diversos formatos de instrucción (que se enumeran en "Op & Format"), así como detalles sobre la sintaxis del código de operación.
- Consulta el documento sobre el formato de archivo
.dex
para obtener más detalles sobre dónde se ajusta el código de bytes en el panorama general.
Resumen del conjunto de código de bytes
Op y formato | Mnemónico o sintaxis | Argumentos | Descripción |
---|---|---|---|
00 10 veces | nop | Ciclos de residuos
Nota: Las pseudoinstrucciones con datos se etiquetan con este código de operación, en cuyo caso el byte de orden superior de la unidad de código de operación indica la naturaleza de los datos. Consulta "Formato |
|
01 12x | move vA, vB | Registro de destino A: (4 bits)Registro de origen B: (4 bits) |
Mueve el contenido de un registro que no es de objeto a otro. |
02 22x | move/from16 vAA, vBBBB | A: registro de destino (8 bits)B: registro de origen (16 bits) |
Mueve el contenido de un registro que no es de objeto a otro. |
03 32x | move/16 vAAAA, vBBBB | Registro de destino A: (16 bits)Registro de origen B: (16 bits) |
Mueve el contenido de un registro que no es de objeto a otro. |
04 12x | vA y vB de movimiento amplio | A: par de registros de destino (4 bits)B: par de registros de origen (4 bits) |
Mueve el contenido de un par de registros a otro.
Nota: Es legal pasar de |
05 22x | move-wide/from16 vAA, vBBBB | A: par de registros de destino (8 bits)B: par de registros de origen (16 bits) |
Mueve el contenido de un par de registros a otro.
Nota:
Las consideraciones de implementación son las mismas que las de |
06 32x | move-wide/16 vAAAA, vBBBB | Par de registros de destino A: (16 bits)Par de registros de origen B: (16 bits) |
Mueve el contenido de un par de registros a otro.
Nota:
Las consideraciones de implementación son las mismas que las de |
07 12x | move-object vA, vB | Registro de destino A: (4 bits)Registro de origen B: (4 bits) |
Mover el contenido de un registro con objetos a otro |
08 22x | move-object/from16 vAA, vBBBB | A: registro de destino (8 bits)B: registro de origen (16 bits) |
Mover el contenido de un registro con objetos a otro |
09 32x | move-object/16 vAAAA, vBBBB | Registro de destino A: (16 bits)Registro de origen B: (16 bits) |
Mover el contenido de un registro con objetos a otro |
0a 11x | vAA de resultado de movimiento | Registro de destino A: (8 bits) |
Mueve el resultado no de objeto de una sola palabra del invoke-kind más reciente al registro indicado.
Esto se debe hacer como la instrucción inmediatamente después de un invoke-kind cuyo resultado (de una sola palabra, no de objeto) no se debe ignorar; en cualquier otro lugar no es válido. |
0b 11x | vAA de move-result-wide | Par de registros de destino A: (8 bits) |
Mueve el resultado de doble palabra del invoke-kind más reciente al par de registros indicado.
Esto se debe hacer como la instrucción inmediatamente después de un invoke-kind cuyo resultado (de doble palabra) no se debe ignorar; en cualquier otro lugar no es válido. |
0c 11x | objeto de resultado de movimiento vAA | Registro de destino A: (8 bits) |
Mueve el resultado del objeto del invoke-kind más reciente al registro indicado. Esto se debe hacer como la instrucción inmediatamente después de un invoke-kind o filled-new-array cuyo resultado (objeto) no se debe ignorar; en cualquier otro lugar no es válido. |
0d 11x | vAA de move-exception | Registro de destino A: (8 bits) |
Guarda una excepción detectada recientemente en el registro determinado. Esta debe ser la primera instrucción de cualquier controlador de excepciones cuya excepción detectada no se deba ignorar, y esta instrucción solo debe ocurrir como la primera instrucción de un controlador de excepciones; en cualquier otro lugar no es válida. |
0e 10x | return-void | Muestra desde un método void . |
|
0f 11x | return vAA | Registro de valor que se muestra A: (8 bits) |
Devuelve desde un método que muestra un valor no de objeto de un solo ancho (32 bits). |
10 11 veces | vAA de todo el retorno | Par de registros del valor que se muestra A: (8 bits) |
Devuelve un método que muestra un valor de doble ancho (64 bits). |
11 11x | return-object vAA | Registro del valor que se muestra A: (8 bits) |
Devuelve desde un método que muestra un objeto. |
12 11n | const/4 vA, #+B | Registro de destino A: (4 bits)Int firmado B: (4 bits) |
Mueve el valor literal determinado (con signo extendido a 32 bits) al registro especificado. |
13 21s | const/16 vAA, #+BBBB | Registro de destino A: (8 bits)Int firmado B: (16 bits) |
Mueve el valor literal determinado (con signo extendido a 32 bits) al registro especificado. |
14 31i | const vAA, #+BBBBBBBB | A: registro de destino (8 bits)B: constante arbitraria de 32 bits |
Mueve el valor literal determinado al registro especificado. |
15 21h | const/high16 vAA, #+BBBB0000 | Registro de destino A: (8 bits)Int firmado B: (16 bits) |
Mueve el valor literal determinado (extendido a la derecha a 32 bits) al registro especificado. |
16 x 21 s | const-wide/16 vAA, #+BBBB | Registro de destino A: (8 bits)Int firmado B: (16 bits) |
Mueve el valor literal determinado (con signo extendido a 64 bits) al par de registros especificado. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | Registro de destino A: (8 bits)Int firmado B: (32 bits) |
Mueve el valor literal determinado (con signo extendido a 64 bits) al par de registros especificado. |
18 51 l | vAA de ancho constante, #+BBBBBBBBBBBBBBBB | Registro de destino A: (8 bits)B: constante arbitraria de doble ancho (64 bits) |
Mueve el valor literal determinado al par de registros especificado. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | Registro de destino A: (8 bits)Int firmado B: (16 bits) |
Mueve el valor literal determinado (extendido a 64 bits a la derecha) al par de registros especificado. |
1a 21c | const-string vAA, string@BBBB | Registro de destino A: (8 bits)Índice de cadena B: |
Mueve una referencia a la cadena especificada por el índice determinado al registro especificado. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | Registro de destino A: (8 bits)Índice de cadena B: |
Mueve una referencia a la cadena especificada por el índice determinado al registro especificado. |
1c 21c | const-class vAA, type@BBBB | Registro de destino A: (8 bits)Índice de tipo B: |
Mueve una referencia a la clase especificada por el índice determinado al registro especificado. En el caso de que el tipo indicado sea primitivo, se almacenará una referencia a la clase degenerada del tipo primitivo. |
1d 11x | monitor-enter vAA | Registro con referencia A: (8 bits) |
Adquiere el monitor para el objeto indicado. |
1e 11x | monitor-exit vAA | Registro con referencia A: (8 bits) |
Libera el monitor del objeto indicado.
Nota: Si esta instrucción necesita generar 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 correctamente (en cierto sentido) y la excepción que se arroja después de la instrucción, pero antes de que la siguiente tenga la oportunidad de ejecutarse. Esta definición permite que un método use un filtro de limpieza de monitores (p.ej., |
1f 21c | check-cast vAA, type@BBBB | A: registro con referencia (8 bits)Índice de tipo B: (16 bits) |
Lanza un ClassCastException si la referencia en el registro determinado no se puede transmitir al tipo indicado.
Nota: Dado que |
20 22c | instance-of vA, vB, type@CCCC | Registro de destino A: (4 bits)Registro de referencia B: (4 bits)Índice de tipo C: (16 bits) |
Almacena en el registro de destino determinado 1 si la referencia indicada es una instancia del tipo determinado o 0 si no es así.
Nota: Dado que |
21 12x | vA, vB de longitud de array | Registro de destino A: (4 bits)Registro de referencia del array B: (4 bits) |
Almacena en el registro de destino determinado la longitud del array indicado, en entradas |
22 21c | new-instance vAA, type@BBBB | Registro de destino A: (8 bits)Índice de tipo B: |
Crea una instancia nueva del tipo indicado y almacena una referencia a ella en el destino. El tipo debe hacer referencia a una clase que no sea de array. |
23 22c | new-array vA, vB, type@CCCC | Registro de destino A: (4 bits)Registro de tamaño B: Índice de tipo C: |
Crea un nuevo array del tipo y tamaño indicados. El tipo debe ser un tipo de array. |
24 35c | array-nuevo-completo {vC, vD, vE, vF, vG}, type@BBBB |
A: Tamaño del array y recuento de palabras de argumentos (4 bits)Índice de tipo B: (16 bits)Registros de argumentos C..G: (4 bits cada uno)
|
Construye un array del tipo y tamaño determinado y complétalo con el contenido proporcionado. El tipo debe ser un tipo de array. El contenido del array debe ser de una sola palabra (es decir, no hay arrays de long o double , pero se aceptan tipos de referencia). La instancia creada se almacena como un "resultado" de la misma manera que las instrucciones de invocación de métodos almacenan sus resultados, por lo que la instancia creada se debe mover a un registro con una instrucción move-result-object inmediatamente posterior (si se va a usar). |
25 3rc | filled-new-array/range {vCCCC .. vNNNN}, type@BBBB | A: Tamaño del array y recuento de palabras de argumentos (8 bits)Índice de tipo B: (16 bits)Registro del primer argumento C: (16 bits)N = A + C - 1 |
Construye un array del tipo y tamaño determinado y complétalo con el contenido proporcionado. Las aclaraciones y restricciones son las mismas que las de filled-new-array , que se describieron anteriormente. |
26 31 t | fill-array-data vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en “Formato fill-array-data-payload ”) |
Referencia de array A: (8 bits)Desplazamiento de “rama” firmado B: a la pseudoinstrucción de datos de la tabla
(32 bits)
|
Completa el array determinado con los datos indicados. La referencia debe ser a un array de primitivas, y la tabla de datos debe coincidir con ella en el tipo y no debe contener más elementos que los que caben en el array. Es decir, el array puede ser más grande que la tabla y, de ser así, solo se establecen los elementos iniciales del array, dejando el resto solo. |
27 11x | arroja vAA | Registro con excepción A: (8 bits) |
Lanza la excepción indicada. |
28 10t | goto +AA | Desplazamiento de rama firmado A: (8 bits) |
Salta de forma incondicional a la instrucción indicada.
Nota:
El desplazamiento de la rama no debe ser |
29 20 t | goto/16 +AAAA | Desplazamiento de rama firmado A: (16 bits) |
Salta de forma incondicional a la instrucción indicada.
Nota:
El desplazamiento de la rama no debe ser |
2a 30t | goto/32 +AAAAAAAA | Desplazamiento de rama firmado A: (32 bits) |
Salta de forma incondicional a la instrucción indicada. |
2b 31t | conmutador empaquetado vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en “Formato packed-switch-payload ”) |
Registro A: para probarOffset de “rama” firmado B: a la pseudoinstrucción de datos de la tabla
(32 bits)
|
Saltar a una instrucción nueva según el valor del registro determinado, con una tabla de desplazamientos correspondientes a cada valor en un rango integral en particular, o bien pasar a la siguiente instrucción si no hay coincidencias |
2c 31t | sparse-switch vAA, +BBBBBBBB (con datos complementarios como se especifica a continuación en “Formato sparse-switch-payload ”) |
Registro A: para probarOffset de “rama” firmado B: a la pseudoinstrucción de datos de la tabla
(32 bits)
|
Saltar a una instrucción nueva según el valor del registro determinado, con una tabla ordenada de pares de valores y desplazamientos, o bien pasar a la siguiente instrucción si no hay coincidencias |
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: registro de destino (8 bits)B: primer registro o par de origenC: segundo registro o par de origen |
Realiza la comparación indicada de punto flotante o long , y establece a en 0 si es b == c , 1 si es b > c o -1 si es b < c .
El "sesgo" que se indica para las operaciones de punto flotante indica cómo se tratan las comparaciones de NaN : las instrucciones de "sesgo superior" muestran 1 para las comparaciones de NaN , y las instrucciones de "sesgo inferior" muestran -1 .
Por ejemplo, para comprobar si un número de punto flotante es |
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: primer registro para probar (4 bits)B: segundo registro para probar (4 bits)C: desplazamiento de rama firmado (16 bits) |
Realiza una bifurcación al destino determinado si los valores de los dos registros determinados se comparan como se especifica.
Nota:
El desplazamiento de la rama no debe ser |
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 |
Registro A: para probar (8 bits)Desplazamiento de rama firmado B: (16 bits) |
Realiza una bifurcación al destino determinado si el valor del registro determinado se compara con 0 como se especifica.
Nota:
El desplazamiento de la rama no debe ser |
3e..43 10x | (sin usar) | (sin usar) | |
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 |
Registro o par de valores A: (puede ser fuente o destino) (8 bits)Registro de array B: (8 bits)Registro de índice C: (8 bits) |
Realiza la operación de array identificada en el índice identificado del array determinado y carga o almacena en el registro de valores. |
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 |
Registro o par de valores A: ; puede ser fuente o destino (4 bits)Registro de objetos B: (4 bits)Índice de referencia de campo de instancia C: (16 bits) |
Realiza la operación de campo de instancia de objeto identificado con el campo identificado, cargándolo o almacenándolo en el registro de valores.
Nota: Estos códigos de operación son candidatos razonables para la vinculación estática, ya que modifican el argumento del campo para que sea un desplazamiento más directo. |
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 |
Registro o par de valores A: ; puede ser fuente o destino (8 bits)Índice de referencia de campo estático B: (16 bits) |
Realiza 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 valores.
Nota: Estos códigos de operación son candidatos razonables para la vinculación estática, ya que modifican el argumento de campo para que sea un desplazamiento más directo. |
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 |
Recuento de palabras del argumento A: (4 bits)Índice de referencia del método B: (16 bits)Registros de argumentos C..G: (4 bits cada uno)
|
Llama al método indicado. El resultado (si corresponde) se puede almacenar con una variante move-result* adecuada como la instrucción inmediatamente posterior.
Cuando En los archivos DEX de la versión
Nota: Estos opcodes son candidatos razonables para la vinculación estática, ya que alteran el argumento del método para que sea un desplazamiento más directo (o un par de ellos). |
73 10x | (sin usar) | (sin usar) | |
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 |
Cantidad de palabras del argumento A: (8 bits)Índice de referencia del método B: (16 bits)Registro del primer argumento C: (16 bits)N = A + C - 1 |
Llama al método indicado. Consulta la primera descripción de invoke-kind que aparece más arriba para obtener detalles, advertencias y sugerencias.
|
79..7a 10x | (sin usar) | (sin usar) | |
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: registro o par de destino (4 bits)B: registro o par de origen (4 bits) |
Realiza la operación unaria identificada en el registro de origen y almacena el resultado en el registro de destino. |
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: registro o par de destino (8 bits)B: primer registro o par de origen (8 bits)C: segundo registro o par de origen (8 bits) |
Realiza la operación binaria identificada en los dos registros de origen y almacena el resultado en el registro de destino.
Nota: Contrario a otras operaciones matemáticas de |
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: registro o par de destino y primer registro o par de origen (4 bits)B: registro o par de segundo origen (4 bits) |
Realiza la operación binaria identificada en los dos registros de origen y almacena el resultado en el primer registro de origen.
Nota: Al contrario de otras operaciones matemáticas de |
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 |
Registro de destino A: (4 bits)Registro de origen B: (4 bits)Constante de int firmada C: (16 bits) |
Realiza la operación binaria indicada en el registro indicado (primer argumento) y el valor literal (segundo argumento), y almacena el resultado en el registro de destino.
Nota:
|
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 |
Registro de destino A: (8 bits)Registro de origen B: (8 bits)Constante int firmada C: (8 bits) |
Realiza la operación binaria indicada en el registro indicado (primer argumento) y el valor literal (segundo argumento), y almacena el resultado en el registro de destino.
Nota: Consulta a continuación para obtener detalles sobre la semántica de |
e3..f9 10x | (sin usar) | (sin usar) | |
fa 45 cc | invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH |
Cantidad de palabras de argumentos A: (4 bits) Índice de referencia del método B: (16 bits) Receptor C: (4 bits) Registros de argumentos D..G: (4 bits cada uno) Índice de referencia del prototipo H: (16 bits)
|
Invoca el método polimórfico de firma indicado. El resultado (si corresponde) se puede almacenar con una variante move-result* adecuada como la instrucción inmediatamente posterior.La referencia del método debe ser a 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 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 devolución 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 los archivos DEX a partir de la versión 038 .
|
fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH |
Recuento de palabras de argumentos A: (8 bits) Índice de referencia del método B: (16 bits) Receptor C: (16 bits) Índice de referencia del prototipo H: (16 bits) N = A + C - 1
|
Invoca el controlador de método indicado. Consulta la descripción de invoke-polymorphic que aparece más arriba para obtener más detalles.Presente en los archivos DEX a partir de la versión 038 .
|
fc 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB |
Recuento de palabras de argumentos A: (4 bits) Índice de referencia del sitio de llamada B: (16 bits) Registros de argumentos C..G: (4 bits cada uno)
|
Resuelve e invoca el lugar de la llamada indicado.
El resultado de la invocación (si la hay) se puede almacenar con una variante move-result* adecuada como la instrucción inmediatamente posterior.Esta instrucción se ejecuta en dos fases: resolución del sitio de llamada y su invocación. La resolución del sitio de llamada verifica si el sitio de llamada indicado tiene una instancia de java.lang.invoke.CallSite asociada.
De lo contrario, se invoca el método del vinculador de arranque para el sitio de llamada indicado con argumentos presentes en el archivo DEX (consulta call_site_item). El método del vinculador de inicio muestra una instancia de java.lang.invoke.CallSite que, luego, se asociará con el sitio de llamada indicado si no existe una asociación. Es posible que otro subproceso ya haya establecido la asociación primero y, de ser así, la ejecución de la instrucción continuará con la primera instancia asociada de java.lang.invoke.CallSite .La invocación del sitio de llamada se realiza en el objetivo java.lang.invoke.MethodHandle de la instancia java.lang.invoke.CallSite resuelta. El objetivo se invoca como si se ejecutara invoke-polymorphic (descrito anteriormente) con el identificador de método y los argumentos de la instrucción invoke-custom como los argumentos de una invocación exacta del identificador de método.Las excepciones que genera el método del vinculador de arranque se unen en un java.lang.BootstrapMethodError . También se genera una BootstrapMethodError en los siguientes casos:
038 .
|
fd 3rc | invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB |
A: recuento de palabras de argumentos (8 bits) B: índice de referencia del sitio de llamada (16 bits) C: registro del primer argumento (16 bits) N = A + C - 1
|
Resuelve e invoca un sitio de llamada. Consulta la descripción de invoke-custom que aparece más arriba para obtener más detalles.Presente en los archivos DEX a partir de la versión 038 .
|
fe 21c | const-method-handle vAA, method_handle@BBBB | Registro de destino A: (8 bits)Índice de identificador de método B: (16 bits) |
Mueve una referencia al identificador de método especificado por el índice determinado al registro especificado. Presente en los archivos DEX a partir de la versión 039 .
|
ff 21c | const-method-type vAA, proto@BBBB | Registro de destino A: (8 bits)Referencia del prototipo del método B: (16 bits) |
Mueve una referencia al prototipo del método especificado por el índice determinado al registro especificado. Presente en los archivos DEX a partir de la versión 039 .
|
Formato de carga útil de interruptor empaquetado
Name | Formato | Descripción |
---|---|---|
identificador | ushort = 0x0100 | identificación del pseudocódigo |
size | ushort | cantidad de entradas en la tabla |
first_key | int | primer (y más bajo) valor de case |
objetivos | int[] | Es una lista de destinos de ramas relativas size . Los destinos se relacionan con la dirección del código de operación de cambio, no con esta tabla.
|
Nota: La cantidad total de unidades de código para una instancia de esta tabla es (size * 2) + 4
.
Formato de carga útil de interruptores dispersos
Name | Formato | Descripción |
---|---|---|
identificador | ushort = 0x0200 | identificación del pseudocódigo |
size | ushort | cantidad de entradas en la tabla |
llaves | int[] | Es una lista de valores de clave size , ordenados de menor a mayor. |
objetivos | int[] | Es una lista de destinos de rama relativos size , cada uno de los cuales corresponde al valor de clave en el mismo índice. Los destinos se relacionan con la dirección del código de operación de cambio, no con esta tabla.
|
Nota: La cantidad total de unidades de código para una instancia de esta tabla es (size * 4) + 2
.
Formato de carga útil de datos de array de relleno
Name | Formato | Descripción |
---|---|---|
identificador | ushort = 0x0300 | identificación del pseudocódigo |
element_width | ushort | cantidad de bytes en cada elemento |
size | uint | cantidad de elementos en la tabla |
datos | ubyte[] | valores de datos |
Nota: La cantidad 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 punto flotante deben seguir las reglas del estándar IEEE 754, con redondeo al número más cercano y desbordamiento gradual, excepto cuando se indique lo contrario.
Código de operación | Semántica de C | Notas |
---|---|---|
neg-int | int32 a; int32 result = -a; |
Complemento a dos unario |
not-int | int32 a; int32 result = ~a; |
Complemento a uno unario |
neg-long | int64 a; int64 result = -a; |
Complemento a dos unario |
not-long | int64 a; int64 result = ~a; |
Complemento a uno unario |
neg-float | float a; float result = -a; |
Negación de punto flotante. |
neg-double | double a; double result = -a; |
Negación de punto flotante. |
int a long | int32 a; int64 result = (int64) a; |
Firma la extensión de int32 en int64 . |
int a float | int32 a; float result = (float) a; |
Conversión de int32 a float con redondeo al número más cercano Esto pierde precisión para algunos valores.
|
int-to-double | int32 a; double result = (double) a; |
Conversión de int32 a double . |
long-to-int | int64 a; int32 result = (int32) a; |
Truncamiento de int64 en int32 . |
long-to-float | int64 a; float result = (float) a; |
Conversión de int64 a float con redondeo al número más cercano Esto pierde precisión para algunos valores.
|
de largo a doble | int64 a; double result = (double) a; |
Conversión de int64 a double con redondeo al número más cercano Esto pierde precisión para algunos valores.
|
float-to-int | float a; int32 result = (int32) a; |
Conversión de float a int32 , con redondeo hacia cero NaN y -0.0 (cero negativo) se convierten en el número entero 0 . Los infinitos y los valores con una magnitud demasiado grande para representarse se convierten en 0x7fffffff o -0x80000000 según el signo.
|
de número de punto flotante a número largo | float a; int64 result = (int64) a; |
Conversión de float a int64 , con redondeo hacia cero Aquí se aplican las mismas reglas de casos especiales que para float-to-int , excepto que los valores fuera de rango se convierten en 0x7fffffffffffffff o -0x8000000000000000 según el signo.
|
float-to-double | float a; double result = (double) a; |
Conversión de float a double , que conserva el valor de forma exacta
|
double-to-int | double a; int32 result = (int32) a; |
Conversión de double a int32 , con redondeo hacia cero Aquí se aplican las mismas reglas de casos especiales que para float-to-int .
|
de doble a largo | double a; int64 result = (int64) a; |
Conversión de double a int64 , con redondeo hacia cero Aquí se aplican las mismas reglas de casos especiales que para float-to-long .
|
double-to-float | double a; float result = (float) a; |
Conversión de double a float con redondeo al número más cercano Esto pierde precisión para algunos valores.
|
int-to-byte | int32 a; int32 result = (a << 24) >> 24; |
Reducción de int32 a int8 , firma que extiende el resultado.
|
int-to-char | int32 a; int32 result = a & 0xffff; |
Reducción de int32 a uint16 , sin extensión de signo
|
int-to-short | int32 a; int32 result = (a << 16) >> 16; |
Reducción de int32 a int16 , firma que extiende el resultado.
|
add-int | int32 a, b; int32 result = a + b; |
Suma de complemento a dos. |
sub-int | int32 a, b; int32 result = a - b; |
Resta de complemento a dos |
rsub-int | int32 a, b; int32 result = b - a; |
Resta inversa de complemento a dos |
mul-int | int32 a, b; int32 result = a * b; |
Multiplicación de complemento a dos. |
div-int | int32 a, b; int32 result = a / b; |
División de complemento a dos, redondeada hacia cero (es decir, truncada a número entero). Esto arroja ArithmeticException si b == 0 .
|
rem-int | int32 a, b; int32 result = a % b; |
Es el resto en complemento a dos después de la 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 .
|
and-int | int32 a, b; int32 result = a & b; |
AND a nivel de bits. |
or-int | int32 a, b; int32 result = a | b; |
OR bit a bit. |
xor-int | int32 a, b; int32 result = a ^ b; |
XOR a nivel de bits. |
shl-int | int32 a, b; int32 result = a << (b & 0x1f); |
Desplazamiento de bits a la izquierda (con argumento enmascarado). |
shr-int | int32 a, b; int32 result = a >> (b & 0x1f); |
Desplazamiento de bits firmado a la derecha (con argumento enmascarado). |
ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); |
Desplazamiento de bits sin signo a la derecha (con argumento enmascarado). |
add-long | int64 a, b; int64 result = a + b; |
Suma de complemento a dos. |
sublongitudinal | int64 a, b; int64 result = a - b; |
Resta de complemento a dos |
mul-long | int64 a, b; int64 result = a * b; |
Multiplicación de complemento a dos. |
div-long | int64 a, b; int64 result = a / b; |
División de complemento a dos, redondeada hacia cero (es decir, truncada a número entero). Esto arroja ArithmeticException si b == 0 .
|
rem-long | int64 a, b; int64 result = a % b; |
Es el resto en complemento a dos después de la 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 .
|
and-long | int64 a, b; int64 result = a & b; |
AND a nivel de bits. |
or-long | int64 a, b; int64 result = a | b; |
OR bit a bit. |
xor-long | int64 a, b; int64 result = a ^ b; |
XOR a nivel de bits. |
shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); |
Desplazamiento de bits a la izquierda (con argumento enmascarado). |
shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); |
Desplazamiento de bits firmado a la derecha (con argumento enmascarado). |
ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); |
Desplazamiento de bits sin signo a la derecha (con argumento enmascarado). |
add-float | float a, b; float result = a + b; |
Suma de números de punto flotante. |
subflotante | float a, b; float result = a - b; |
Resta de punto flotante. |
mul-float | float a, b; float result = a * b; |
Multiplicación de números de punto flotante. |
div-float | float a, b; float result = a / b; |
División de punto flotante. |
rem-float | float a, b; float result = a % b; |
Es el resto de punto flotante después de la división. Esta función es diferente del resto de IEEE 754 y se define como result == a - roundTowardZero(a / b) * b .
|
add-double | double a, b; double result = a + b; |
Suma de números de punto flotante. |
subdoble | double a, b; double result = a - b; |
Resta de punto flotante. |
mul-double | double a, b; double result = a * b; |
Multiplicación de números de punto flotante. |
div-double | double a, b; double result = a / b; |
División de punto flotante. |
rem-double | double a, b; double result = a % b; |
Es el resto de punto flotante después de la división. Esta función es diferente del resto de IEEE 754 y se define como result == a - roundTowardZero(a / b) * b .
|