Projeto geral
- O modelo da máquina e as convenções de chamada destinam-se a imitar aproximadamente arquiteturas reais comuns e convenções de chamada no estilo C:
- A máquina é baseada em registro e os quadros têm tamanho fixo no momento da criação. Cada quadro consiste em um determinado número de registros (especificados pelo método), bem como quaisquer dados auxiliares necessários para executar o método, como (mas não limitado a) o contador do programa e uma referência ao arquivo
.dex
que contém o método . - Quando usados para valores de bits (como inteiros e números de ponto flutuante), os registradores são considerados com largura de 32 bits. Pares de registros adjacentes são usados para valores de 64 bits. Não há nenhum requisito de alinhamento para pares de registros.
- Quando usados para referências de objetos, os registradores são considerados amplos o suficiente para conter exatamente uma dessas referências.
- Em termos de representação bit a bit,
(Object) null == (int) 0
. - Os N argumentos para um método chegam aos últimos N registros do quadro de invocação do método, em ordem. Argumentos amplos consomem dois registros. Os métodos de instância recebem
this
referência como seu primeiro argumento.
- A máquina é baseada em registro e os quadros têm tamanho fixo no momento da criação. Cada quadro consiste em um determinado número de registros (especificados pelo método), bem como quaisquer dados auxiliares necessários para executar o método, como (mas não limitado a) o contador do programa e uma referência ao arquivo
- A unidade de armazenamento no fluxo de instruções é uma quantidade não assinada de 16 bits. Alguns bits em algumas instruções são ignorados/devem ser zero.
- As instruções não são limitadas gratuitamente a um tipo específico. Por exemplo, instruções que movem valores de registradores de 32 bits sem interpretação não precisam especificar se estão movendo ints ou floats.
- Existem conjuntos de constantes enumerados e indexados separadamente para referências a strings, tipos, campos e métodos.
- Os dados literais bit a bit são representados em linha no fluxo de instruções.
- Como, na prática, é incomum que um método precise de mais de 16 registradores, e como a necessidade de mais de oito registradores é razoavelmente comum, muitas instruções são limitadas a abordar apenas os primeiros 16 registradores. Quando razoavelmente possível, as instruções permitem referências aos primeiros 256 registros. Além disso, algumas instruções têm variantes que permitem contagens de registros muito maiores, incluindo um par de instruções de
move
abrangentes que podem endereçar registros no intervalov0
–v65535
. Nos casos em que uma variante de instrução não está disponível para endereçar um registrador desejado, espera-se que o conteúdo do registrador seja movido do registrador original para um registrador baixo (antes da operação) e/ou movido de um registrador de resultado baixo para um registrador alto. registrar (após a operação). - Existem várias "pseudo-instruções" usadas para armazenar cargas úteis de dados de comprimento variável, que são referidas por instruções regulares (por exemplo,
fill-array-data
). Tais instruções nunca devem ser encontradas durante o fluxo normal de execução. Além disso, as instruções devem estar localizadas em deslocamentos de bytecode pares (ou seja, alinhados em 4 bytes). Para atender a esse requisito, as ferramentas de geração dex devem emitir uma instruçãonop
extra como espaçador, caso tal instrução fique desalinhada. Finalmente, embora não seja obrigatório, espera-se que a maioria das ferramentas opte por emitir essas instruções no final dos métodos, caso contrário, provavelmente seriam necessárias instruções adicionais para diversificá-las. - Quando instaladas em um sistema em execução, algumas instruções podem ser alteradas, alterando seu formato, como uma otimização de link estático no momento da instalação. Isso permite uma execução mais rápida quando a ligação for conhecida. Consulte o documento de formatos de instruções associados para as variantes sugeridas. A palavra “sugerido” é usada deliberadamente; não é obrigatório implementá-los.
- Sintaxe humana e mnemônicos:
- Ordenação destino-então-fonte para argumentos.
- Alguns opcodes têm um sufixo de nome desambiguante para indicar o(s) tipo(s) em que operam:
- Os opcodes de tipo geral de 32 bits não estão marcados.
- Os códigos de operação gerais de 64 bits têm o sufixo
-wide
. - Os opcodes específicos do tipo são sufixados com seu tipo (ou uma abreviatura direta), um dos seguintes:
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- Alguns opcodes têm um sufixo de desambiguação para distinguir operações idênticas que possuem diferentes layouts ou opções de instruções. Esses sufixos são separados dos nomes principais por uma barra ("
/
") e existem principalmente para fazer com que haja um mapeamento um-para-um com constantes estáticas no código que gera e interpreta executáveis (ou seja, para reduzir a ambiguidade para humanos). - Nas descrições aqui, a largura de um valor (indicando, por exemplo, o intervalo de uma constante ou o número de registros possivelmente endereçados) é enfatizada pelo uso de um caractere por quatro bits de largura.
- Por exemplo, na instrução "
move-wide/from16 vAA, vBBBB
":- "
move
" é o opcode base, indicando a operação base (mover o valor de um registrador). - "
wide
" é o sufixo do nome, indicando que ele opera em dados amplos (64 bits). - "
from16
" é o sufixo do opcode, indicando uma variante que possui uma referência de registro de 16 bits como origem. - "
vAA
" é o registrador de destino (implícito na operação; novamente, a regra é que os argumentos de destino sempre vêm primeiro), que deve estar no intervalov0
–v255
. - "
vBBBB
" é o registro fonte, que deve estar no intervalov0
–v65535
.
- "
- Consulte o documento de formatos de instruções para obter mais detalhes sobre os vários formatos de instruções (listados em "Op & Format"), bem como detalhes sobre a sintaxe do opcode.
- Consulte o documento de formato de arquivo
.dex
para obter mais detalhes sobre onde o bytecode se encaixa no quadro geral.
Resumo do conjunto de bytes
Operação e formato | Mnemônico/Sintaxe | Argumentos | Descrição |
---|---|---|---|
00 10x | não, não | Ciclos de resíduos. Nota: Pseudo-instruções contendo dados são marcadas com este opcode, caso em que o byte de ordem superior da unidade do opcode indica a natureza dos dados. Consulte "formato | |
01 12x | mover vA, vB | A: registro de destino (4 bits)B: registro de origem (4 bits) | Mova o conteúdo de um registro não-objeto para outro. |
02 22x | mover/de16 vAA, vBBBB | A: registro de destino (8 bits)B: registro de origem (16 bits) | Mova o conteúdo de um registro não-objeto para outro. |
03 32x | movimento/16 vAAAA, vBBBB | A: registro de destino (16 bits)B: registro de origem (16 bits) | Mova o conteúdo de um registro não-objeto para outro. |
04 12x | movimento amplo vA, vB | A: par de registradores de destino (4 bits)B: par de registradores de origem (4 bits) | Mova o conteúdo de um par de registros para outro. Nota: É legal passar de |
05 22x | move-wide/from16 vAA, vBBBB | A: par de registradores de destino (8 bits)B: par de registradores de origem (16 bits) | Mova o conteúdo de um par de registros para outro. Nota: As considerações de implementação são as mesmas do |
06 32x | move-wide/16 vAAAA, vBBBB | A: par de registradores de destino (16 bits)B: par de registradores de origem (16 bits) | Mova o conteúdo de um par de registros para outro. Nota: As considerações de implementação são as mesmas do |
07 12x | mover objeto vA, vB | A: registro de destino (4 bits)B: registro de origem (4 bits) | Mova o conteúdo de um registro portador de objeto para outro. |
08 22x | mover-objeto/from16 vAA, vBBBB | A: registro de destino (8 bits)B: registro de origem (16 bits) | Mova o conteúdo de um registro portador de objeto para outro. |
09 32x | mover-objeto/16 vAAAA, vBBBB | A: registro de destino (16 bits)B: registro de origem (16 bits) | Mova o conteúdo de um registro portador de objeto para outro. |
0a 11x | resultado da movimentação vAA | A: registro de destino (8 bits) | Mova o resultado não-objeto de palavra única do invoke- kind mais recente para o registro indicado. Isso deve ser feito como a instrução imediatamente após uma invoke- kind cujo resultado (palavra única, não-objeto) não deve ser ignorado; em qualquer outro lugar é inválido. |
0b 11x | vAA para todo o resultado da movimentação | A: par de registradores de destino (8 bits) | Mova o resultado da palavra dupla do invoke- kind mais recente para o par de registradores indicado. Isso deve ser feito como a instrução imediatamente após um invoke- kind cujo resultado (palavra dupla) não deve ser ignorado; em qualquer outro lugar é inválido. |
0c 11x | mover-objeto de resultado vAA | A: registro de destino (8 bits) | Mova o resultado do objeto do invoke- kind mais recente para o registro indicado. Isso deve ser feito como a instrução imediatamente após um invoke- kind ou filled-new-array cujo resultado (objeto) não deve ser ignorado; em qualquer outro lugar é inválido. |
0d 11x | exceção de movimento vAA | A: registro de destino (8 bits) | Salve uma exceção recém-capturada no registro fornecido. Esta deve ser a primeira instrução de qualquer manipulador de exceção cuja exceção capturada não deve ser ignorada, e esta instrução só deve ocorrer como a primeira instrução de um manipulador de exceção; em qualquer outro lugar é inválido. |
0e 10x | retorno vazio | Retornar de um método void . | |
0f 11x | retornar vAA | A: registrador de valor de retorno (8 bits) | Retornar de um método de retorno de valor sem objeto de largura única (32 bits). |
10 11x | vAA para todo o retorno | A: par de registradores de valor de retorno (8 bits) | Retornar de um método de retorno de valor de largura dupla (64 bits). |
11 11x | objeto de retorno vAA | A: registrador de valor de retorno (8 bits) | Retornar de um método de retorno de objeto. |
12 11n | const/4 vA, #+B | A: registro de destino (4 bits)B: int assinado (4 bits) | Mova o valor literal fornecido (com sinal estendido para 32 bits) para o registro especificado. |
13 21s | const/16 vAA, #+BBB | A: registro de destino (8 bits)B: int assinado (16 bits) | Mova o valor literal fornecido (com sinal estendido para 32 bits) para o registro especificado. |
14 31i | const vAA, #+BBBBBBB | A: registro de destino (8 bits)B: constante arbitrária de 32 bits | Mova o valor literal fornecido para o registro especificado. |
15 21h | const/alta16 vAA, #+BBBB0000 | A: registro de destino (8 bits)B: int assinado (16 bits) | Mova o valor literal fornecido (zero à direita estendido para 32 bits) para o registro especificado. |
16 21s | largura const/16 vAA, #+BBBB | A: registro de destino (8 bits)B: int assinado (16 bits) | Mova o valor literal fornecido (sinal estendido para 64 bits) para o par de registros especificado. |
17 31i | largura const/32 vAA, #+BBBBBBBB | A: registro de destino (8 bits)B: int assinado (32 bits) | Mova o valor literal fornecido (sinal estendido para 64 bits) para o par de registros especificado. |
18 51l | vAA em toda a const, #+BBBBBBBBBBBBBB | A: registro de destino (8 bits)B: constante arbitrária de largura dupla (64 bits) | Mova o valor literal fornecido para o par de registros especificado. |
19 21h | const-amplo/alto16 vAA, #+BBBB000000000000 | A: registro de destino (8 bits)B: int assinado (16 bits) | Mova o valor literal fornecido (zero à direita estendido para 64 bits) para o par de registros especificado. |
1a 21c | const-string vAA, string@BBBB | A: registro de destino (8 bits)B: índice de string | Mova uma referência à string especificada pelo índice fornecido para o registro especificado. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | A: registro de destino (8 bits)B: índice de string | Mova uma referência à string especificada pelo índice fornecido para o registro especificado. |
1c 21c | classe const vAA, tipo@BBBB | A: registro de destino (8 bits)B: índice de tipo | Mova uma referência à classe especificada pelo índice fornecido para o registro especificado. No caso em que o tipo indicado é primitivo, armazenará uma referência à classe degenerada do tipo primitivo. |
1d 11x | monitor-entrada vAA | A: registro de referência (8 bits) | Adquira o monitor para o objeto indicado. |
1e 11x | saída do monitor vAA | A: registro de referência (8 bits) | Solte o monitor para o objeto indicado. Nota: Se esta instrução precisar lançar uma exceção, ela deverá fazê-lo como se o pc já tivesse avançado além da instrução. Pode ser útil pensar nisso como a instrução sendo executada com sucesso (em certo sentido), e a exceção sendo lançada após a instrução, mas antes que a próxima tenha a chance de ser executada. Esta definição torna possível que um método use um bloco pega-tudo de limpeza de monitor (por exemplo, |
1f 21c | check-cast vAA, digite@BBBB | A: registro de referência (8 bits)B: índice de tipo (16 bits) | Lança uma ClassCastException se a referência no registro fornecido não puder ser convertida para o tipo indicado. Nota: Como |
20 22c | instância de vA, vB, tipo@CCCC | A: registro de destino (4 bits)B: registro de referência (4 bits)C: índice de tipo (16 bits) | Armazene no registrador de destino fornecido 1 se a referência indicada for uma instância do tipo determinado, ou 0 se não for. Nota: Como |
21 12x | comprimento da matriz vA, vB | A: registro de destino (4 bits)B: registro de referência de matriz (4 bits) | Armazene no registrador de destino fornecido o comprimento do array indicado, em entradas |
22 21c | nova instância vAA, digite@BBBB | A: registro de destino (8 bits)B: índice de tipo | Construa uma nova instância do tipo indicado, armazenando uma referência a ela no destino. O tipo deve se referir a uma classe que não seja de array. |
23 22c | nova matriz vA, vB, tipo@CCCC | A: registro de destino (4 bits)B: registro de tamanhoC: índice de tipo | Construa uma nova matriz do tipo e tamanho indicados. O tipo deve ser um tipo de matriz. |
24 35c | nova matriz preenchida {vC, vD, vE, vF, vG}, tipo@BBBB | A: tamanho do array e contagem de palavras de argumento (4 bits)B: índice de tipo (16 bits)C..G: registradores de argumentos (4 bits cada) | Construa um array de determinado tipo e tamanho, preenchendo-o com o conteúdo fornecido. O tipo deve ser um tipo de matriz. O conteúdo do array deve ser de palavra única (ou seja, nenhum array de long ou double , mas tipos de referência são aceitáveis). A instância construída é armazenada como um "resultado" da mesma forma que as instruções de invocação de método armazenam seus resultados, portanto a instância construída deve ser movida para um registro com uma instrução move-result-object imediatamente subsequente (se for usada ). |
25 3rc | nova matriz/intervalo preenchido {vCCCC .. vNNNN}, digite@BBBB | A: tamanho do array e contagem de palavras de argumento (8 bits)B: índice de tipo (16 bits)C: registro do primeiro argumento (16 bits)N = A + C - 1 | Construa um array de determinado tipo e tamanho, preenchendo-o com o conteúdo fornecido. Esclarecimentos e restrições são iguais aos de filled-new-array , descritos acima. |
26 31t | fill-array-data vAA, +BBBBBBBB (com dados suplementares conforme especificado abaixo em "formato fill-array-data-payload ") | A: referência de array (8 bits)B: deslocamento de "ramificação" assinado para pseudo-instrução de dados da tabela (32 bits) | Preencha o array fornecido com os dados indicados. A referência deve ser a um array de primitivos, e a tabela de dados deve corresponder ao tipo e não deve conter mais elementos do que cabem no array. Ou seja, o array pode ser maior que a tabela e, nesse caso, apenas os elementos iniciais do array são definidos, deixando o restante em paz. |
27 11x | lançar vAA | A: registro portador de exceção (8 bits) | Lance a exceção indicada. |
28 10t | ir para +AA | A: deslocamento de ramificação assinada (8 bits) | Salte incondicionalmente para a instrução indicada. Nota: O deslocamento da ramificação não deve ser |
29 20t | ir para/16 +AAAA | A: deslocamento de ramificação assinada (16 bits) | Salte incondicionalmente para a instrução indicada. Nota: O deslocamento da ramificação não deve ser |
2h30 | ir para/32 +AAAAAAAA | A: deslocamento de ramificação assinada (32 bits) | Salte incondicionalmente para a instrução indicada. |
2b 31t | pack-switch vAA, +BBBBBBBB (com dados suplementares conforme especificado abaixo em "formato packed-switch-payload ") | A: registre-se para testarB: deslocamento de "ramificação" assinado para pseudo-instrução de dados da tabela (32 bits) | Salte para uma nova instrução com base no valor no registro fornecido, usando uma tabela de deslocamentos correspondentes a cada valor em um intervalo integral específico, ou passe para a próxima instrução se não houver correspondência. |
2c 31t | sparse-switch vAA, +BBBBBBBB (com dados suplementares conforme especificado abaixo em "formato sparse-switch-payload ") | A: registre-se para testarB: deslocamento de "ramificação" assinado para pseudo-instrução de dados da tabela (32 bits) | Pule para uma nova instrução com base no valor no registro fornecido, usando uma tabela ordenada de pares valor-deslocamento, ou passe para a próxima instrução se não houver correspondência. |
2d..31 23x | cmp tipo vAA, vBB, vCC 2d: cmpl-float (viés lt) 2e: cmpg-float (viés gt) 2f: cmpl-double (tendência lt) 30: cmpg-double (viés gt) 31: cmp de comprimento | A: registro de destino (8 bits)B: primeiro registro ou par de fonteC: segundo registro ou par de fonte | Execute o ponto flutuante indicado ou comparação long , definindo a como 0 se b == c , 1 se b > c ou -1 se b < c . O "viés" listado para as operações de ponto flutuante indica como as comparações NaN são tratadas: as instruções "gt polarização" retornam 1 para comparações NaN e as instruções "lt polarização" retornam -1 . Por exemplo, para verificar se o ponto flutuante |
32..37 22t | se- teste vA, vB, +CCCC 32: se-eq 33: se não 34: se-lt 35: se-ge 36: se-gt 37: se-le | A: primeiro registro a testar (4 bits)B: segundo registro para testar (4 bits)C: deslocamento de ramificação assinada (16 bits) | Ramifique para o destino fornecido se os valores dos dois registros fornecidos forem comparados conforme especificado. Nota: O deslocamento da ramificação não deve ser |
38..3d 21t | se- teste z vAA, +BBBB 38: se-eqz 39: if-nez 3a: se-ltz 3b: se-gez 3c: se-gtz 3d: if-lez | A: registre-se para testar (8 bits)B: deslocamento de ramificação assinada (16 bits) | Ramifique para o destino fornecido se o valor do registro fornecido for comparado com 0 conforme especificado. Nota: O deslocamento da ramificação não deve ser |
3e..43 10x | (não utilizado) | (não utilizado) | |
44..51 23x | arrayop vAA, vBB, vCC 44: idade 45: toda a idade 46: objeto-aget 47: age-booleano 48: age-byte 49: idade-char 4a: falta de idade 4b: colocar 4c: largura de entrada 4d: objeto aput 4e: aput-booleano 4f: byte de entrada 50: aput-char 51: aput-curto | A: registrador ou par de valores; pode ser origem ou destino (8 bits)B: registrador de matriz (8 bits)C: registrador de índice (8 bits) | Execute a operação do array identificado no índice identificado do array fornecido, carregando ou armazenando no registrador de valor. |
52..5f 22c | eu instânciaop vA, vB, campo@CCCC 52: iget 53: iget-largo 54: objeto iget 55: iget-booleano 56: iget byte 57: iget-char 58: iget-curto 59: eu coloco 5a: todo o iput 5b: objeto iput 5c: iput-booleano 5d: byte de entrada 5e: iput-char 5f: iput-curto | A: registrador ou par de valores; pode ser origem ou destino (4 bits)B: registro de objeto (4 bits)C: índice de referência de campo de instância (16 bits) | Execute a operação de campo da instância do objeto identificado com o campo identificado, carregando ou armazenando no registrador de valor. Nota: Esses opcodes são candidatos razoáveis para vinculação estática, alterando o argumento do campo para ser um deslocamento mais direto. |
60..6d 21c | s staticop vAA, campo@BBBB 60: chegar 61: todo o espaço 62: objeto sget 63: sget-booleano 64: sget-byte 65: sget-char 66: sget-curto 67: cuspir 68: todo o espectro 69: objeto sput 6a: sput-booleano 6b: byte de saída 6c: caractere de saída 6d: cuspido curto | A: registrador ou par de valores; pode ser origem ou destino (8 bits)B: índice de referência de campo estático (16 bits) | Execute a operação do campo estático do objeto identificado com o campo estático identificado, carregando ou armazenando no registrador de valor. Nota: Esses opcodes são candidatos razoáveis para vinculação estática, alterando o argumento do campo para ser um deslocamento mais direto. |
6e..72 35c | invocar- tipo {vC, vD, vE, vF, vG}, meth@BBBB 6e: invocar-virtual 6f: invocar-super 70: invocar direto 71: invocar-estático 72: interface de invocação | A: contagem de palavras de argumento (4 bits)B: índice de referência do método (16 bits)C..G: registradores de argumentos (4 bits cada) | Chame o método indicado. O resultado (se houver) pode ser armazenado com uma variante move-result* apropriada como a instrução imediatamente subsequente. Quando o Nos arquivos Dex versão Nota: Esses opcodes são candidatos razoáveis para vinculação estática, alterando o argumento do método para ser um deslocamento mais direto (ou par deles). |
73 10x | (não utilizado) | (não utilizado) | |
74..78 3rc | invocar- tipo / intervalo {vCCCC .. vNNNN}, meth@BBBB 74: invocar-virtual/intervalo 75: invocar-super/intervalo 76: invocar direto/intervalo 77: invocar-estático/intervalo 78: interface de invocação/intervalo | A: contagem de palavras de argumento (8 bits)B: índice de referência do método (16 bits)C: registro do primeiro argumento (16 bits)N = A + C - 1 | Chame o método indicado. Veja a primeira descrição invoke- kind acima para obter detalhes, advertências e sugestões. |
79..7a 10x | (não utilizado) | (não utilizado) | |
7b..8f 12x | unop vA, vB 7b: neg-int 7c: não-int 7d: neg-longo 7e: não muito tempo 7f: neg-float 80: negativo-duplo 81: inteiro para longo 82: int para float 83: int-para-duplo 84: longo para int 85: longo para flutuar 86: longo para dobrar 87: float para int 88: flutuante para longo 89: float para duplo 8a: duplo para int 8b: duplo para longo 8c: duplo para flutuar 8d: int para byte 8e: int-to-char 8f: int-para-curto | A: registro ou par de destino (4 bits)B: registro ou par de origem (4 bits) | Execute a operação unária identificada no registrador de origem, armazenando o resultado no registrador de destino. |
90..af 23x | binop vAA, vBB, vCC 90: suplemento 91: sub-int 92: mul-int 93: div-int 94: rem-int 95: e-int 96: ou-int 97: xor-int 98: shl-int 99: sh-int 9a: ushr-int 9b: adição longa 9c: sublongo 9d: mul-longo 9e: div-longo 9f: rem-longo a0: e-longo a1: ou longo a2: xor-longo a3: shl-longo a4: shr-longo a5: ushr-longo a6: adicionar float a7: subflutuante a8: mul-float a9: div-float aa: rem-float ab: adição-duplo ac: sub-duplo anúncio: mul-duplo ae: div-duplo af: rem-duplo | A: registro ou par de destino (8 bits)B: primeiro registro ou par de origem (8 bits)C: segundo registro ou par de fonte (8 bits) | Execute a operação binária identificada nos dois registradores de origem, armazenando o resultado no registrador de destino. Nota: Ao contrário de outras operações matemáticas |
b0..cf 12x | binop /2endereço vA, vB b0: add-int/2addr b1: subint/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: e-int/2addr b6: ou-int/2addr b7: xor-int/2addr b8: shl-int/2addr b9: shr-int/2addr ba: ushr-int/2addr bb: add-long/2addr bc: sub-longo/2addr bd: mul-long/2addr ser: div-long/2addr bf: rem-long/2addr c0: e-longo/2addr c1: ou-longo/2addr c2: xor-long/2addr c3: shl-longo/2addr c4: shr-longo/2addr c5: ushr-long/2addr c6: adicionar-float/2addr c7: subfloat/2addr c8: mul-float/2addr c9: div-float/2addr ca: rem-float/2addr cb: adicionar-duplo/2addr cc: subduplo/2addr cd: mul-duplo/2addr ce: div-double/2addr cf: rem-duplo/2addr | A: destino e primeiro registrador ou par de origem (4 bits)B: segundo registro ou par de fonte (4 bits) | Execute a operação binária identificada nos dois registradores fonte, armazenando o resultado no primeiro registrador fonte. Nota: Ao contrário de outras operações matemáticas |
d0..d7 22s | binop /lit16 vA, vB, #+CCCC d0: add-int/lit16 d1: rsub-int (subtração reversa) d2: mul-int/lit16 d3: div-int/lit16 d4: rem-int/lit16 d5: e-int/lit16 d6: ou-int/lit16 d7: xor-int/lit16 | A: registro de destino (4 bits)B: registro de origem (4 bits)C: constante int assinada (16 bits) | Execute a operação binária indicada no registrador indicado (primeiro argumento) e no valor literal (segundo argumento), armazenando o resultado no registrador de destino. Nota: |
d8..e2 22b | binop /lit8 vAA, vBB, #+CC d8: add-int/lit8 d9: rsub-int/lit8 da: mul-int/lit8 banco de dados: div-int/lit8 dc: rem-int/lit8 dd: and-int/lit8 de: or-int/lit8 df: xor-int/lit8 e0: shl-int/lit8 e1: shr-int/lit8 e2: ushr-int/lit8 | A: registro de destino (8 bits)B: registro de origem (8 bits)C: constante int assinada (8 bits) | Execute a operação binária indicada no registrador indicado (primeiro argumento) e no valor literal (segundo argumento), armazenando o resultado no registrador de destino. Nota: Veja abaixo detalhes sobre a semântica de |
e3..f9 10x | (não utilizado) | (não utilizado) | |
fa 45cc | invocar-polimórfico {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH | A: contagem de palavras de argumento (4 bits)B: índice de referência do método (16 bits)C: receptor (4 bits)D..G: registradores de argumentos (4 bits cada)H: índice de referência do protótipo (16 bits) | Invoque o método polimórfico de assinatura indicado. O resultado (se houver) pode ser armazenado com uma variante move-result* apropriada como a instrução imediatamente subsequente.A referência do método deve ser um método polimórfico de assinatura, como java.lang.invoke.MethodHandle.invoke ou java.lang.invoke.MethodHandle.invokeExact .O receptor deve ser um objeto que suporte o método polimórfico de assinatura que está sendo invocado. A referência do protótipo descreve os tipos de argumentos fornecidos e o tipo de retorno esperado. O bytecode invoke-polymorphic pode gerar exceções quando é executado. As exceções estão descritas na documentação da API para o método polimórfico de assinatura que está sendo invocado.Presente em arquivos Dex a partir da versão 038 . |
fb4rcc | invocar-polimórfico/intervalo {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH | A: contagem de palavras de argumento (8 bits)B: índice de referência do método (16 bits)C: receptor (16 bits)H: índice de referência do protótipo (16 bits)N = A + C - 1 | Invoque o identificador do método indicado. Veja a descrição invoke-polymorphic acima para obter detalhes.Presente em arquivos Dex a partir da versão 038 . |
FC 35c | invocar-custom {vC, vD, vE, vF, vG}, call_site@BBBB | A: contagem de palavras de argumento (4 bits)B: índice de referência do site de chamada (16 bits)C..G: registradores de argumentos (4 bits cada) | Resolve e invoca o site de chamada indicado. O resultado da invocação (se houver) pode ser armazenado com uma variante move-result* apropriada como a instrução imediatamente subsequente.Esta instrução é executada em duas fases: resolução do site de chamada e invocação do site de chamada. A resolução do site de chamada verifica se o site de chamada indicado possui uma instância java.lang.invoke.CallSite associada. Caso contrário, o método do vinculador bootstrap para o site de chamada indicado é invocado usando argumentos presentes no arquivo DEX (consulte call_site_item ). O método do vinculador bootstrap retorna uma instância java.lang.invoke.CallSite que será então associada ao site de chamada indicado se nenhuma associação existir. Outro encadeamento pode já ter feito a associação primeiro e, nesse caso, a execução da instrução continua com a primeira instância java.lang.invoke.CallSite associada.A invocação do site de chamada é feita no destino java.lang.invoke.MethodHandle da instância java.lang.invoke.CallSite resolvida. O destino é invocado como se estivesse executando invoke-polymorphic (descrito acima) usando o identificador do método e os argumentos para a instrução invoke-custom como os argumentos para uma invocação exata do identificador do método.As exceções levantadas pelo método do vinculador de bootstrap são agrupadas em java.lang.BootstrapMethodError . Um BootstrapMethodError também será gerado se:
038 . |
fd3rc | invocar-custom/intervalo {vCCCC .. vNNNN}, call_site@BBBB | A: contagem de palavras de argumento (8 bits)B: índice de referência do site de chamada (16 bits)C: registro do primeiro argumento (16 bits)N = A + C - 1 | Resolva e invoque um site de chamada. Consulte a descrição invoke-custom acima para obter detalhes.Presente em arquivos Dex a partir da versão 038 . |
fe 21c | const-method-handle vAA, method_handle@BBBB | A: registro de destino (8 bits)B: índice de identificador de método (16 bits) | Mova uma referência ao identificador de método especificado pelo índice fornecido para o registro especificado. Presente em arquivos Dex a partir da versão 039 . |
ff 21c | tipo de método const vAA, proto@BBBB | A: registro de destino (8 bits)B: referência de protótipo de método (16 bits) | Mova uma referência ao protótipo do método especificado pelo índice fornecido para o registro especificado. Presente em arquivos Dex a partir da versão 039 . |
formato de carga útil de switch compactado
Nome | Formatar | Descrição |
---|---|---|
identificar | ucurto = 0x0100 | identificando pseudo-opcode |
tamanho | ucurto | número de entradas na tabela |
primeira_chave | interno | primeiro (e mais baixo) valor do switch case |
alvos | interno[] | lista de alvos de ramificação relativa size . Os alvos são relativos ao endereço do opcode do switch, não desta tabela. |
Nota: O número total de unidades de código para uma instância desta tabela é (size * 2) + 4
.
formato de carga útil de switch esparso
Nome | Formatar | Descrição |
---|---|---|
identificar | ucurto = 0x0200 | identificando pseudo-opcode |
tamanho | ucurto | número de entradas na tabela |
chaves | interno[] | lista de valores-chave size , classificados de menor para maior |
alvos | interno[] | lista de alvos de ramificação relativos size , cada um correspondendo ao valor-chave no mesmo índice. Os alvos são relativos ao endereço do opcode do switch, não desta tabela. |
Nota: O número total de unidades de código para uma instância desta tabela é (size * 4) + 2
.
formato de carga útil de dados de matriz de preenchimento
Nome | Formatar | Descrição |
---|---|---|
identificar | ucurto = 0x0300 | identificando pseudo-opcode |
largura_do_elemento | ucurto | número de bytes em cada elemento |
tamanho | unint | número de elementos na tabela |
dados | ubyte[] | valores de dados |
Nota: O número total de unidades de código para uma instância desta tabela é (size * element_width + 1) / 2 + 4
.
Detalhes da operação matemática
Nota: As operações de ponto flutuante devem seguir as regras IEEE 754, usando underflow arredondado para mais próximo e gradual, exceto quando indicado de outra forma.
Código de operação | Semântica C | Notas |
---|---|---|
neg-int | int32a; resultado int32 = -a; | Complemento unário de dois. |
não-int | int32a; resultado int32 = ~a; | Unário-complemento. |
neg-longo | int64a; resultado int64 = -a; | Complemento unário de dois. |
não muito | int64a; resultado int64 = ~a; | Unário-complemento. |
neg-float | flutuar um; resultado flutuante = -a; | Negação de ponto flutuante. |
negativo-duplo | duplo a; resultado duplo = -a; | Negação de ponto flutuante. |
INT-LONG | int32 a; INT64 resultado = (int64) a; | Extensão de sinal de int32 em int64 . |
INT para flutuar | int32 a; resultado flutuante = (flutuação) a; | Conversão de int32 para float , usando redondo para o mais. Isso perde precisão para alguns valores. |
int-duplo | int32 a; resultado duplo = (duplo) a; | Conversão de int32 para double . |
longo a inseguro | int64 a; INT32 resultado = (int32) a; | Truncamento de int64 em int32 . |
longo a flutuar | int64 a; resultado flutuante = (flutuação) a; | Conversão de int64 para float , usando redondo para o mais. Isso perde precisão para alguns valores. |
longo, duplo | int64 a; resultado duplo = (duplo) a; | Conversão de int64 para double , usando arredondamento para o mais. Isso perde precisão para alguns valores. |
Float-to-Int | flutuar a; INT32 resultado = (int32) a; | Conversão de float para int32 , usando rodovias-zero. NaN e -0.0 (zero negativo) se convertem para o número inteiro 0 . Infinidades e valores com uma magnitude muito grande a serem representados são convertidos em 0x7fffffff ou -0x80000000 , dependendo do sinal. |
flutuar a longo | flutuar a; INT64 resultado = (int64) a; | Conversão de float para int64 , usando zero-galo-zero. As mesmas regras de caso especiais que, para float-to-int se aplicam aqui, exceto que os valores fora da faixa são convertidos em 0x7fffffffffffffff ou -0x8000000000000000 , dependendo da sinal. |
Float-to-Double | flutuar a; resultado duplo = (duplo) a; | Conversão de float para double , preservando exatamente o valor. |
duplo para intimidar | duplo a; INT32 resultado = (int32) a; | Conversão de double em int32 , usando rodovias-zero. As mesmas regras de caso especiais que, para float-to-int se aplicam aqui. |
duplo a longo | duplo a; INT64 resultado = (int64) a; | Conversão de double em int64 , usando rodovias-zero. As mesmas regras de caso especiais que para float-to-long se aplicam aqui. |
duplo a flutuar | duplo a; resultado flutuante = (flutuação) a; | Conversão de double em float , usando redondo para o mais. Isso perde precisão para alguns valores. |
int-byte | int32 a; INT32 resultado = (a << 24) >> 24; | Truncamento de int32 a int8 , assinar estendendo o resultado. |
INT-TO-CHAR | int32 a; INT32 resultado = a e 0xffff; | Truncamento de int32 a uint16 , sem extensão de sinal. |
INT-Para-Short | int32 a; int32 resultado = (a << 16) >> 16; | Truncamento de int32 a int16 , signo estendendo o resultado. |
add-int | int32 a, b; INT32 resultado = a + b; | Adição de dois complementos. |
Sub-Int | int32 a, b; INT32 resultado = a - b; | Subtração de complemento de dois. |
rsub-int | int32 a, b; Int32 resultado = b - a; | Subtração reversa reversa de complemento de dois. |
Mul-Int | int32 a, b; INT32 resultado = a * b; | Multiplicação de dois com complementos. |
Div-Int | int32 a, b; INT32 resultado = a / b; | Divisão de complemento de dois, arredondados para zero (ou seja, truncado para o número inteiro). Isso lança ArithmeticException se b == 0 . |
REM-INT | int32 a, b; INT32 resultado = A % B; | O restante do complemento de dois dois após a divisão. O sinal do resultado é o mesmo que o de a e é mais precisamente definido como result == a - (a / b) * b . Isso lança ArithmeticException se b == 0 . |
e-int | int32 a, b; INT32 Result = A & B; | Bit nejudado e. |
ou-insa | int32 a, b; INT32 resultado = a | b; | Bit nejudado ou. |
XOR-INT | int32 a, b; INT32 resultado = a ^ b; | Bitwise xor. |
shl-int | int32 a, b; int32 resultado = a << (b & 0x1f); | Mudança Bitwise para a esquerda (com argumento mascarado). |
shr-int | int32 a, b; INT32 resultado = a >> (b & 0x1f); | Bitwise Shift, sinalizado à direita (com argumento mascarado). |
ushr-int | uint32 a, b; INT32 resultado = a >> (b & 0x1f); | Mudança não assinada bitwise (com argumento mascarado). |
add-longo | int64 a, b; INT64 resultado = a + b; | Adição de dois complementos. |
sub-longo | int64 a, b; INT64 resultado = a - b; | Subtração de complemento de dois. |
MuL-Long | int64 a, b; INT64 resultado = a * b; | Multiplicação de dois com complementos. |
div-long | int64 a, b; INT64 resultado = a / b; | Divisão de complemento de dois, arredondados para zero (ou seja, truncado para o número inteiro). Isso lança ArithmeticException se b == 0 . |
Rem-longo | int64 a, b; resultado int64 = a % b; | O restante do complemento de dois dois após a divisão. O sinal do resultado é o mesmo que o de a e é mais precisamente definido como result == a - (a / b) * b . Isso lança ArithmeticException se b == 0 . |
e longo | int64 a, b; INT64 resultado = A&B; | Bit nejudado e. |
ou longo | int64 a, b; INT64 resultado = a | b; | Bit nejudado ou. |
Xor-longo | int64 a, b; INT64 resultado = a ^ b; | Bitwise xor. |
shl-longo | int64 a; int32 b; INT64 resultado = a << (b & 0x3f); | Mudança Bitwise para a esquerda (com argumento mascarado). |
short-long | int64 a; int32 b; INT64 resultado = a >> (b & 0x3f); | Bitwise Shift, sinalizado à direita (com argumento mascarado). |
Ushr-Long | uint64 a; int32 b; INT64 resultado = a >> (b & 0x3f); | Mudança não assinada bitwise (com argumento mascarado). |
add-float | flutuar a, b; resultado flutuante = a + b; | Adição de ponto flutuante. |
Sub-float | flutuar a, b; resultado flutuante = a - b; | Subtração de ponto flutuante. |
mul-fl-float | flutuar a, b; resultado flutuante = a * b; | Multiplicação de ponto flutuante. |
div-float | flutuar a, b; resultado flutuante = a / b; | Divisão de ponto flutuante. |
REM-FLOAT | flutuar a, b; resultado flutuante = a % b; | Ponto flutuante restante após a divisão. Esta função é diferente do restante do IEEE 754 e é definida como result == a - roundTowardZero(a / b) * b . |
add-dupla | duplo a, b; resultado duplo = a + b; | Adição de ponto flutuante. |
sub-duplo | duplo a, b; resultado duplo = a - b; | Subtração de ponto flutuante. |
Mul-duplo | duplo a, b; resultado duplo = a * b; | Multiplicação de ponto flutuante. |
Div-dupla | duplo a, b; resultado duplo = a / b; | Divisão de ponto flutuante. |
Rem-duplo | duplo a, b; resultado duplo = a % b; | Ponto flutuante restante após a divisão. Esta função é diferente do restante do IEEE 754 e é definida como result == a - roundTowardZero(a / b) * b . |