Aprendendo Assembly
Doar para o autor
  • Introdução
  • Conteúdo
  • Como usar este livro
  • A base
    • Noção geral da arquitetura
    • Modos de operação
    • Sintaxe
    • Registradores de propósito geral
    • Endereçamento
    • Pilha
    • Saltos
    • Procedimentos
    • Seções e símbolos
    • Instruções assembly x86
    • Instruções do NASM
    • Pré-processador do NASM
    • Syscall no Linux
    • Olá mundo no Linux
    • Revisão
  • Aprofundando em Assembly
    • Registradores de segmento
    • CALL e RET
    • Position-independent executable
    • Atributos
    • Prefixos
    • Flags do processador
    • Instruções condicionais
    • Programando no MS-DOS
    • Interrupções de software e exceções
    • Procedimentos do BIOS
    • Usando instruções da FPU
    • Entendendo SSE
      • Instruções de movimentação de dados
      • Instruções aritméticas
      • Instruções lógicas e de comparação
      • Instruções com inteiros 128-bit
      • Instruções de conversão
  • Programando junto com C
    • Sintaxe do GAS
    • Convenção de chamada da System V ABI
    • Convenções de chamada no Windows
    • Variáveis em C
    • Funções em C
    • Ambiente hosted
    • Ambiente freestanding
    • Inline Assembly no GCC
    • Instruções intrínsecas
  • Depuração de código
    • Entendendo os depuradores
    • Depurando com o GDB
    • Depurando com o Dosbox
  • Apêndices
    • Código de máquina
      • Formato das instruções
      • Atributos e prefixos
      • Immediate
      • Displacement
      • ModR/M e SIB
      • Opcode
      • Prefixo REX
      • Codificação dos registradores
  • Metadados
    • TO DO
    • Referências
Powered by GitBook
On this page
  • BIT D
  • BIT S

Was this helpful?

Export as PDF
  1. Apêndices
  2. Código de máquina

Opcode

Entendendo o opcode da instrução.

PreviousModR/M e SIBNextPrefixo REX

Last updated 2 years ago

Was this helpful?

Como já foi dito antes existem opcodes cujo os 3 últimos bits são usados para identificar o registrador usado na instrução. Opcodes nesse estilo de codificação são usados para instruções que só precisam usar um registrador. Por exemplo mov eax, 123 cujo o opcode é B8.

Já em instruções que usam o os dois bits menos significativos do opcode tem um significado especial, que são chamados de bit D (direction bit) e S (size bit). Conforme ilustração:

BIT D

A função do bit D é indicar a direção para onde a operação está sendo executada. Se do REG para o R/M ou vice-versa. Repare nas instruções abaixo e seus respectivos opcodes:

mov eax, [ebx] ; 8B03
mov [ebx], eax ; 8903

Convertendo os opcodes 8B e 89 para binário dá para notar um fato interessante:

8B -> 10001011
89 -> 10001001

A única diferença entre os opcodes é que em um o bit D está ligado e no outro não. Quando o bit D está ligado o campo REG é usado como operando destino e o campo R/M usado como fonte. E quando ele está desligado é o inverso: o campo R/M é o destino e o REG é o fonte. Obviamente o mesmo também se aplica se o R/M também for um registrador.

Por exemplo a instrução xor eax, eax pode ser escrita em código de máquina como 31 C0 ou 33 C0. Como no campo REG e no campo R/M são os mesmos registradores não faz diferença qual é o fonte e qual é o destino, a operação executada será a mesma. Usando um disassembler como o ndisasm dá para notar isso:

felipe@silva-lenovo:~$ echo -ne "\x31\xC0\x33\xC0" > tst
felipe@silva-lenovo:~$ ndisasm -b32 tst
00000000  31C0              xor eax,eax
00000002  33C0              xor eax,eax

BIT S

O bit S é usado para definir o tamanho do operando, onde:

  • 0 -> Indica que o operando é de 8-bit

  • 1 -> Indica que o operando é do tamanho do operand-size.

Repare por exemplo a instrução 30 C0:

felipe@silva-lenovo:~$ echo -ne "\x30\xC0" > tst
felipe@silva-lenovo:~$ ndisasm -b32 tst
00000000  30C0              xor al,al

Onde 31 C0 (com o bit S ligado) usa o operando de 32-bit EAX. Mas 30 C0 usa o operando de 8-bit AL.

Repare também no seguinte caso:

felipe@silva-lenovo:~$ echo -ne "\x66\x30\xC0\x66\x31\xC0" > tst
felipe@silva-lenovo:~$ ndisasm -b32 tst
00000000  6630C0            o16 xor al,al
00000003  6631C0            xor ax,ax

Veja que ao usar o prefixo 66 () em 31 C0 o registrador AX é utilizado. Mas esse prefixo é ignorado em instruções cujo o bit S esteja desligado. Por isso o ndisasm faz o disassembly da instrução ainda como xor al, al. Embora ele adicione um o16 ali para denotar o uso (inútil) do prefixo.

byte ModR/M
Representação dos bits de um opcode.
operand-size override