Projeto geral
- O modelo de 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 tamanhos dos quadros são fixados na criação. Cada quadro consiste em um número específico de registradores (especificado pelo método), bem como quaisquer dados adjuntos 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 usado para valores de bits (como números inteiros e números de ponto flutuante), os registradores são considerados com 32 bits de largura. Pares de registradores adjacentes são usados para valores de 64 bits. Não há requisito de alinhamento para pares de registradores.
- 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 aterrissam nos ú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 uma referência
this
como seu primeiro argumento.
- A máquina é baseada em registro e os tamanhos dos quadros são fixados na criação. Cada quadro consiste em um número específico de registradores (especificado pelo método), bem como quaisquer dados adjuntos 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 sem sinal 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 inteiros 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 porque a necessidade de mais de oito registradores é razoavelmente comum, muitas instruções são limitadas a apenas endereçar os primeiros 16 registradores. Quando razoavelmente possível, as instruções permitem referências até os primeiros 256 registradores. Além disso, algumas instruções têm variantes que permitem contagens de registradores muito maiores, incluindo um par de instruções de
move
catch-all que podem endereçar registradores 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" que são 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 de número par (ou seja, alinhados com 4 bytes). Para atender a esse requisito, as ferramentas de geração dex devem emitir uma instruçãonop
extra como um espaçador se tal instrução for desalinhada. Finalmente, embora não seja obrigatório, espera-se que a maioria das ferramentas opte por emitir essas instruções nas extremidades dos métodos, pois, caso contrário, provavelmente seriam necessárias instruções adicionais para ramificá-las. - Quando instalado em um sistema em execução, algumas instruções podem ser alteradas, alterando seu formato, como uma otimização de link estático em tempo de instalação. Isso é para permitir uma execução mais rápida assim que a ligação for conhecida. Consulte o documento de formatos de instrução associados para as variantes sugeridas. A palavra "sugerido" é usada com cautela; não é obrigatório implementá-los.
- Sintaxe humana e mnemônicos:
- Ordenação de dest-then-source 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 são marcados.
- Os opcodes de tipo geral de 64 bits são sufixados com
-wide
. - Os opcodes específicos de tipo são sufixados com seu tipo (ou uma abreviação 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 de instruções ou opções. Estes sufixos são separados dos nomes principais por uma barra ("
/
") e existem principalmente para fazer um mapeamento um-para-um com constantes estáticas no código que gera e interpreta os executáveis (isto é, 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 opera em dados amplos (64 bits). - "
from16
" é o sufixo opcode, indicando uma variante que tem uma referência de registro de 16 bits como fonte. - "
vAA
" é o registrador de destino (implicado pela operação; novamente, a regra é que os argumentos de destino sempre venham primeiro), que deve estar no intervalov0
–v255
. - "
vBBBB
" é o registro de origem, que deve estar no intervalov0
–v65535
.
- "
- Consulte o documento de formatos de instrução para obter mais detalhes sobre os vários formatos de instrução (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 bytecodes
Operação e formato | Mnemônico / Sintaxe | Argumentos | Descrição |
---|---|---|---|
00 10x | não | Ciclos de resíduos. Nota: As pseudo-instruções portadoras de dados são marcadas com este opcode, caso em que o byte de ordem superior da unidade opcode indica a natureza dos dados. Consulte "Formato | |
01 12x | mover vA, vB | A: registrador de destino (4 bits)B: registrador de origem (4 bits) | Mova o conteúdo de um registrador não-objeto para outro. |
02 22x | mover/de16 vAA, vBBBB | A: registrador de destino (8 bits)B: registrador de origem (16 bits) | Mova o conteúdo de um registrador não-objeto para outro. |
03 32x | mover/16 vAAAA, vBBBB | A: registrador de destino (16 bits)B: registrador de origem (16 bits) | Mova o conteúdo de um registrador 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 registradores para outro. Nota: É legal mover 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 registradores para outro. Nota: As considerações de implementação são as mesmas que |
06 32x | movimento amplo/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 registradores para outro. Nota: As considerações de implementação são as mesmas que |
07 12x | mover-objeto vA, vB | A: registrador de destino (4 bits)B: registrador de origem (4 bits) | Mova o conteúdo de um registrador portador de objeto para outro. |
08 22x | move-object/from16 vAA, vBBBB | A: registrador de destino (8 bits)B: registrador de origem (16 bits) | Mova o conteúdo de um registrador portador de objeto para outro. |
09 32x | move-object/16 vAAAA, vBBBB | A: registrador de destino (16 bits)B: registrador de origem (16 bits) | Mova o conteúdo de um registrador portador de objeto para outro. |
0a 11x | movimento-resultado vAA | A: registrador de destino (8 bits) | Mova o resultado não-objeto de palavra única do invoke- kind mais recente para o registrador indicado. Isso deve ser feito como a instrução imediatamente após um invoke- kind cujo resultado (palavra única, não objeto) não deve ser ignorado; qualquer outro lugar é inválido. |
0b 11x | vAA para todo o resultado do movimento | A: par de registradores de destino (8 bits) | Mova o resultado de 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; qualquer outro lugar é inválido. |
0c 11x | mover-resultado-objeto vAA | A: registrador de destino (8 bits) | Mova o resultado do objeto do invoke- kind mais recente para o registrador 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; qualquer outro lugar é inválido. |
0d 11x | exceção de movimento vAA | A: registrador 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 essa instrução deve ocorrer apenas como a primeira instrução de um manipulador de exceção; qualquer outro lugar é inválido. |
0e 10x | retorno nulo | Retorno de um método void . | |
0f 11x | retornar vAA | A: registrador de valor de retorno (8 bits) | Retorno de um método de retorno de valor sem objeto de largura única (32 bits). |
10 11x | vAA de retorno | A: valor de retorno par de registradores (8 bits) | Retorno 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) | Retorno de um método de retorno de objeto. |
12 11n | const/4vA, #+B | A: registrador de destino (4 bits)B: assinado int (4 bits) | Mova o valor literal fornecido (sinal estendido para 32 bits) no registrador especificado. |
13 21s | const/16vAA, #+BBBB | A: registrador de destino (8 bits)B: assinado int (16 bits) | Mova o valor literal fornecido (sinal estendido para 32 bits) no registrador especificado. |
14 31i | const vAA, #+BBBBBBBB | A: registrador de destino (8 bits)B: constante arbitrária de 32 bits | Mova o valor literal fornecido para o registrador especificado. |
15 21h | const/high16 vAA, #+BBBB0000 | A: registrador de destino (8 bits)B: assinado int (16 bits) | Mova o valor literal fornecido (extensão de zero à direita para 32 bits) no registrador especificado. |
16 21s | const-wide/16 vAA, #+BBBB | A: registrador de destino (8 bits)B: assinado int (16 bits) | Mova o valor literal fornecido (sinal estendido para 64 bits) no par de registradores especificado. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: registrador de destino (8 bits)B: assinado int (32 bits) | Mova o valor literal fornecido (sinal estendido para 64 bits) no par de registradores especificado. |
18 51l | vAA const-wide, #+BBBBBBBBBBBBBBBB | A: registrador de destino (8 bits)B: constante arbitrária de largura dupla (64 bits) | Mova o valor literal fornecido para o par de registradores especificado. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: registrador de destino (8 bits)B: assinado int (16 bits) | Mova o valor literal fornecido (extensão de zero à direita para 64 bits) para o par de registradores especificado. |
1a 21c | const-string vAA, string@BBBB | A: registrador de destino (8 bits)B: índice de strings | Mova uma referência à string especificada pelo índice fornecido para o registrador especificado. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | A: registrador de destino (8 bits)B: índice de strings | Mova uma referência à string especificada pelo índice fornecido para o registrador especificado. |
1c 21c | vAA classe const, digite @BBBB | A: registrador de destino (8 bits)B: índice de tipo | Mova uma referência à classe especificada pelo índice fornecido para o registrador especificado. No caso em que o tipo indicado for primitivo, isso armazenará uma referência à classe degenerada do tipo primitivo. |
1d 11x | monitor-entrar vAA | A: registrador de referência (8 bits) | Adquira o monitor para o objeto indicado. |
1e 11x | monitor-saída vAA | A: registrador de referência (8 bits) | Solte o monitor para o objeto indicado. Nota: Se esta instrução precisar lançar uma exceção, deve 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. Essa definição possibilita que um método use um bloco catch-all de limpeza de monitor (por exemplo, |
1f 21c | check-cast vAA, digite @BBBB | A: registrador de referência (8 bits)B: índice de tipo (16 bits) | Lance um ClassCastException se a referência no registrador fornecido não puder ser convertida para o tipo indicado. Nota: Como |
20 22c | instância de vA, vB, tipo@CCCC | A: registrador de destino (4 bits)B: registrador de referência (4 bits)C: tipo índice (16 bits) | Armazenar no registrador de destino dado 1 se a referência indicada for uma instância do tipo dado, ou 0 se não for. Nota: Como |
21 12x | comprimento da matriz vA, vB | A: registrador de destino (4 bits)B: registro de referência de matriz (4 bits) | Armazenar no registrador de destino dado o comprimento do array indicado, em entradas |
22 21c | vAA de nova instância, digite@BBBB | A: registrador 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 matriz. |
23 22c | nova matriz vA, vB, tipo@CCCC | A: registrador de destino (4 bits)B: registro de tamanhoC: tipo de índice | 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}, digite @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 uma matriz do tipo e tamanho fornecidos, preenchendo-a com o conteúdo fornecido. O tipo deve ser um tipo de matriz. O conteúdo do array deve ser de uma única palavra (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, então a instância construída deve ser movida para um registrador com uma instrução move-result-object imediatamente subsequente (se for usada ). |
25 3rc | nova matriz/intervalo preenchida {vCCCC .. vNNNN}, digite@BBBB | A: tamanho do array e contagem de palavras de argumento (8 bits)B: índice de tipo (16 bits)C: registrador do primeiro argumento (16 bits)N = A + C - 1 | Construa uma matriz do tipo e tamanho fornecidos, preenchendo-a com o conteúdo fornecido. Esclarecimentos e restrições são os mesmos que filled-new-array , descritos acima. |
26 31t | fill-array-data vAA, +BBBBBBBB (com dados suplementares conforme especificado abaixo em " fill-array-data-payload Format") | A: referência de array (8 bits)B: deslocamento "ramo" assinado para pseudo-instrução de dados de tabela (32 bits) | Preencha a matriz fornecida com os dados indicados. A referência deve ser para uma matriz de primitivos, e a tabela de dados deve corresponder a ela em tipo e não deve conter mais elementos do que cabem na matriz. Ou seja, a matriz pode ser maior que a tabela e, se for, apenas os elementos iniciais da matriz são definidos, deixando o restante em paz. |
27 11x | jogar vAA | A: registrador portador de exceção (8 bits) | Lance a exceção indicada. |
28 10t | vá para +AA | A: deslocamento de ramal assinado (8 bits) | Salte incondicionalmente para a instrução indicada. Nota: O deslocamento da ramificação não deve ser |
29 20t | goto/16 +AAAA | A: deslocamento de ramal assinado (16 bits) | Salte incondicionalmente para a instrução indicada. Nota: O deslocamento da ramificação não deve ser |
2a 30t | goto/32 +AAAAAAAA | A: deslocamento de ramal assinado (32 bits) | Salte incondicionalmente para a instrução indicada. |
2b 31t | vAA de switch embalado, +BBBBBBBB (com dados suplementares conforme especificado abaixo em "Formato packed-switch-payload ") | A: cadastre-se para testarB: deslocamento "ramo" assinado para pseudo-instrução de dados de tabela (32 bits) | Pule para uma nova instrução com base no valor no registrador fornecido, usando uma tabela de deslocamentos correspondentes a cada valor em uma faixa integral específica, ou passe para a próxima instrução se não houver correspondência. |
2c 31t | vAA de comutador esparso, +BBBBBBBB (com dados suplementares conforme especificado abaixo em "Formato sparse-switch-payload ") | A: cadastre-se para testarB: deslocamento "ramo" assinado para pseudo-instrução de dados de tabela (32 bits) | Saltar para uma nova instrução com base no valor no registrador fornecido, usando uma tabela ordenada de pares valor-deslocamento, ou passar para a próxima instrução se não houver correspondência. |
2d..31 23x | cmp tipo vAA, vBB, vCC 2d: cmpl-float (polarização lt) 2e: cmpg-float (viés gt) 2f: cmpl-double (polarização lt) 30: cmpg-double (viés gt) 31: cmp de comprimento | A: registrador de destino (8 bits)B: primeiro registrador ou par de fonteC: segundo registrador ou par de origem | Execute o ponto flutuante indicado ou a comparação long , configurando a para 0 se b == c , 1 se b > c ou -1 se b < c . O "bias" listado para as operações de ponto flutuante indica como as comparações NaN são tratadas: as instruções "gt bias" retornam 1 para comparações NaN e as instruções "lt bias" retornam -1 . Por exemplo, para verificar se o ponto flutuante |
32..37 22t | if- teste vA, vB, +CCCC 32: se-eq 33: se-ne 34: se-lt 35: if-ge 36: se-gt 37: if-le | A: primeiro registrador a testar (4 bits)B: segundo registrador a testar (4 bits)C: deslocamento de ramal assinado (16 bits) | Desvia para o destino dado se os valores dos dois registradores forem comparados conforme especificado. Nota: O deslocamento da ramificação não deve ser |
38..3d 21t | if- teste z vAA, +BBBB 38: if-eqz 39: if-nez 3a: if-ltz 3b: if-gez 3c: if-gtz 3d: if-lez | A: registrar para testar (8 bits)B: deslocamento de ramal assinado (16 bits) | Ramifique para o destino dado se o valor do registrador for comparado com 0 conforme especificado. Nota: O deslocamento da ramificação não deve ser |
3e..43 10x | (sem uso) | (sem uso) | |
44..51 23x | arrayop vAA, vBB, vCC 44: obter 45: geral 46: obter-objeto 47: aget-boolean 48: get-byte 49: aget-char 4a: abreviar 4b: colocar 4c: aput-wide 4d: aput-objeto 4e: aput-boolean 4f: byte de entrada 50: aput-char 51: aput-curto | A: registrador ou par de valor; 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 dado, carregando ou armazenando no registrador de valor. |
52..5f 22c | i instanceop vA, vB, field@CCCC 52: iget 53: todo o iget 54: iget-objeto 55: iget-boolean 56: iget-byte 57: iget-char 58: iget-curto 59: entrada 5a: todo o iput 5b: iput-objeto 5c: iput-boolean 5d: iput-byte 5e: iput-char 5f: iput-curto | A: registrador ou par de valor; pode ser origem ou destino (4 bits)B: registrador de objeto (4 bits)C: índice de referência de campo de instância (16 bits) | Execute a operação do 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 de campo para um deslocamento mais direto. |
60..6d 21c | s staticop vAA, field@BBBB 60: começar 61: amplo 62: objeto sget 63: sget-boolean 64: byte sget 65: sget-char 66: curto 67: cuspir 68: em todo o sput 69: objeto sput 6a: sput-boolean 6b: byte de saída 6c: sput-char 6d: cuspe-curto | A: registrador ou par de valor; pode ser origem ou destino (8 bits)B: índice de referência de campo estático (16 bits) | Execute a operação de 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 de campo para um deslocamento mais direto. |
6e..72 35c | tipo de invocação {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 Em arquivos Dex versão Nota: Esses opcodes são candidatos razoáveis para vinculação estática, alterando o argumento do método para um deslocamento mais direto (ou par deles). |
73 10x | (sem uso) | (sem uso) | |
74..78 3rc | invocar- kind /range {vCCCC .. vNNNN}, meth@BBBB 74: invocar-virtual/range 75: invocar-super/range 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: registrador do primeiro argumento (16 bits)N = A + C - 1 | Chame o método indicado. Consulte a descrição do primeiro invoke- kind acima para obter detalhes, advertências e sugestões. |
79..7a 10x | (sem uso) | (sem uso) | |
7b..8f 12x | unop vA, vB 7b: neg-int 7c: não-int 7d: neg-longo 7e: não longo 7f: neg-float 80: duplo negativo 81: int-para-longo 82: int para flutuar 83: int-para-duplo 84: longo para int 85: longo para flutuar 86: longo para duplo 87: float-to-int 88: flutuante para longo 89: flutuar para dobrar 8a: duplo para inteiro 8b: duplo a longo 8c: duplo para flutuar 8d: int para byte 8e: int-to-char 8f: int para curto | A: registrador ou par de destino (4 bits)B: registrador 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.. de 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: add-long 9c: sublongo 9d: mul-longo 9e: div-longo 9f: rem-longo a0: e-longo a1: ou-longo a2: xor-longo a3: shl-longo a4: sh-long a5: ushr-longo a6: add-float a7: sub-float a8: mul-float a9: div-float aa: rem-float ab: add-double ac: sub-duplo anúncio: mul-double ae: div-double af: rem-double | A: registrador ou par de destino (8 bits)B: primeiro registrador ou par de origem (8 bits)C: segundo registrador ou par de origem (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 /2addr vA, vB b0: add-int/2addr b1: sub-int/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: e-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-longo/2addr bd: mul-long/2addr ser: div-long/2addr bf: rem-long/2addr c0: e-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-duplo/2addr cd: mul-double/2addr ce: div-double/2addr cf: rem-double/2addr | A: destino e primeiro registrador ou par de origem (4 bits)B: segundo registrador ou par de origem (4 bits) | Execute a operação binária identificada nos dois registradores de origem, armazenando o resultado no primeiro registrador de origem. 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: or-int/lit16 d7: xor-int/lit16 | A: registrador de destino (4 bits)B: registrador de origem (4 bits)C: constante int assinada (16 bits) | Execute a operação binária indicada no registrador indicado (primeiro argumento) e 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 db: div-int/lit8 dc: rem-int/lit8 dd: e-int/lit8 de: or-int/lit8 df: xor-int/lit8 e0: shl-int/lit8 e1: shr-int/lit8 e2: ushr-int/lit8 | A: registrador de destino (8 bits)B: registrador de origem (8 bits)C: constante int assinada (8 bits) | Execute a operação binária indicada no registrador indicado (primeiro argumento) e valor literal (segundo argumento), armazenando o resultado no registrador de destino. Nota: Veja abaixo os detalhes sobre a semântica de |
e3..f9 10x | (sem uso) | (sem uso) | |
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 para 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 de protótipo descreve os tipos de argumento fornecidos e o tipo de retorno esperado. O bytecode invoke-polymorphic pode gerar exceções quando executado. As exceções sã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 . |
fb 4rcc | 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 de método indicado. Consulte 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 local 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 de site de chamada e invocação de site de chamada. A resolução do site de chamada verifica se o site de chamada indicado tem uma instância java.lang.invoke.CallSite associada. Caso contrário, o método do vinculador de 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 não houver associação. Outro encadeamento já pode 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 chamada do site de chamada é feita no destino java.lang.invoke.MethodHandle da instância java.lang.invoke.CallSite resolvida. O alvo é invocado como se estivesse executando invoke-polymorphic (descrito acima) usando o handle de método e argumentos para a instrução invoke-custom como os argumentos para uma invocação de handle de método exato.As exceções levantadas pelo método do vinculador bootstrap são encapsuladas em um java.lang.BootstrapMethodError . Um BootstrapMethodError também é gerado se:
038 . |
fd 3rc | invocar-custom/range {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: primeiro registro de 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: registrador de destino (8 bits)B: índice de manipulação do método (16 bits) | Mova uma referência ao manipulador de método especificado pelo índice fornecido para o registro especificado. Presente em arquivos Dex da versão 039 em diante. |
ff 21c | vAA do tipo de método const, proto@BBBB | A: registrador de destino (8 bits)B: referência do protótipo do método (16 bits) | Mova uma referência ao protótipo do método especificado pelo índice fornecido para o registrador especificado. Presente em arquivos Dex da versão 039 em diante. |
formato de carga útil de switch compactado
Nome | Formato | Descrição |
---|---|---|
identificação | ushor = 0x0100 | identificando pseudo-opcode |
Tamanho | ushor | número de entradas na tabela |
first_key | int | primeiro (e mais baixo) valor da caixa de comutação |
alvos | int[] | lista de destinos de ramificação relativos ao 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 do switch esparso
Nome | Formato | Descrição |
---|---|---|
identificação | ushor = 0x0200 | identificando pseudo-opcode |
Tamanho | ushor | número de entradas na tabela |
chaves | int[] | lista de valores de chave de size , classificados de baixo para alto |
alvos | int[] | lista de destinos de ramificação relativos ao size , cada um correspondendo ao valor da 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 | Formato | Descrição |
---|---|---|
identificação | ushor = 0x0300 | identificando pseudo-opcode |
element_width | ushor | número de bytes em cada elemento |
Tamanho | uint | 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 arredondada para mais próxima e gradual, exceto onde indicado de outra forma.
Código de operação | Semântica C | Notas |
---|---|---|
neg-int | int32a; int32 resultado = -a; | Complemento de dois unário. |
não-int | int32a; int32 resultado = ~a; | Unários-complemento. |
longo | int64a; int64 resultado = -a; | Complemento de dois unário. |
não muito | int64a; int64 resultado = ~a; | Unários-complemento. |
neg-float | flutuar um; 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 . |