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 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
- 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 rangov0
–v65535
. 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ónnop
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 rangov0
–v255
. - "
vBBBB
" es el registro de origen, que debe estar en el rangov0
–v65535
.
- "
- 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 | |
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 |
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 |
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 |
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., |
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 |
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 |
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ñoC: í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 |
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 |
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 probarB: 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 probarB: 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 parC: 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 |
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 |
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 |
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. Cuando En los archivos Dex versión 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 |
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 |
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: |
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 |
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:
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 . |