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
  • Endereçamento em 16-bit
  • Endereçamento em 32-bit
  • Endereçamento em 64-bit
  • Byte SIB

Was this helpful?

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

ModR/M e SIB

Entendendo os byte ModR/M e SIB.

PreviousDisplacementNextOpcode

Last updated 3 years ago

Was this helpful?

Como já foi mencionado anteriormente o byte ModR/M é usado em algumas instruções para especificar o operando na memória ou registrador.

Em Assembly existem dois "tipos" de instruções que recebem dois operandos:

  1. As que tem um operando registrador e imediato. Exemplo: mov eax, 123

  2. As que tem um operando na memória ou dois operandos registradores. Exemplos: mov [ebx], 123 e mov eax, ebx.

O primeiro tipo não precisa do byte ModR/M, pois o registrador destino é especificado nos 3 últimos bits do byte do . Por exemplo o opcode B8 da instrução mov eax, 123 é o seguinte em binário: 10111000 Onde o número zero (000) é o código para identificar o registrador EAX.

Um jeito mais simples de especificar esse campo no opcode sem precisar lidar com binário é simplesmente somar o opcode "base" (correspondente ao uso de AL/AX/EAX) mais o código do registrador. Por exemplo se a instrução B8 (B8 + 0) corresponde a mov eax, 123, então o opcode BB (B8 + 3) é mov ebx, 123. E se eu quiser fazer mov bx, 123 basta adicionar o prefixo 66 à instrução.

Já as instruções do segundo tipo usam o byte ModR/M para definir o operando destino na memória (no caso de instruções sem o operando registrador) ou os dois operandos. Onde o byte ModR/M consiste nos três campos:

  • MOD - Os primeiros 2 bits que definem o "modo" do operando R/M.

  • REG - Os 3 próximos bits que definem o código do operando registrador.

  • R/M - Os 3 últimos bits que definem o código do operando R/M.

O byte define 2 operandos:

  1. Um operando que é sempre um registrador, definido no campo REG.

  2. Um operando que pode ser um registrador ou operando na memória.

Para que o campo R/M defina também o código de um registrador, assim como o REG, o valor 3 (11 em binário) deve ser usado no campo MOD.

Um adendo sobre o byte ModR/M é que em algumas instruções o campo REG é usado como uma extensão do opcode. É o caso por exemplo das instruções inc dword [ebx] (FF 03) e dec dword [ebx] (FF 0B) que contém o mesmo byte de opcode mas fazem operações diferentes. Repare como o campo R/M é necessário para especificar o operando na memória mas o REG fica "sobrando", por isso os engenheiros da Intel tomaram essa decisão minimamente confusa (vulgo gambiarra), afim de aproveitar dessa peculiaridade em instruções que precisam de um operando na memória mas não precisam de um operando registrador.

Para os demais valores do campo MOD os seguintes endereçamentos são feitos de acordo com o valor de R/M:

Endereçamento em 16-bit

MOD 00

R/M
Endereçamento

000

[BX+SI]

001

[BX+DI]

010

[BP+SI]

011

[BP+DI]

100

[SI]

101

[DI]

110

displacement 16-bit

111

[BX]

MOD 01

R/M
Endereçamento

000

[BX+SI] + displacement 8-bit

001

[BX+DI] + displacement 8-bit

010

[BP+SI] + displacement 8-bit

011

[BP+DI] + displacement 8-bit

100

[SI] + displacement 8-bit

101

[DI] + displacement 8-bit

110

[BP] + displacement 8-bit

111

[BX] + displacement 8-bit

MOD 10

R/M
Endereçamento

000

[BX+SI] + displacement 16-bit

001

[BX+DI] + displacement 16-bit

010

[BP+SI] + displacement 16-bit

011

[BP+DI] + displacement 16-bit

100

[SI] + displacement 16-bit

101

[DI] + displacement 16-bit

110

[BP] + displacement 16-bit

111

[BX] + displacement 16-bit

Endereçamento em 32-bit

MOD 00

R/M
Endereçamento

000

[eax]

001

[ecx]

010

[edx]

011

[ebx]

100

SIB

101

displacement 32-bit

110

[esi]

111

[edi]

MOD 01

R/M
Endereçamento

000

[eax] + displacement 8-bit

001

[ecx] + displacement 8-bit

010

[edx] + displacement 8-bit

011

[ebx] + displacement 8-bit

100

SIB + displacement 8-bit

101

[ebp] + displacement 8-bit

110

[esi] + displacement 8-bit

111

[edi] + displacement 8-bit

MOD 10

R/M
Endereçamento

000

[eax] + displacement 32-bit

001

[ecx] + displacement 32-bit

010

[edx] + displacement 32-bit

011

[ebx] + displacement 32-bit

100

SIB + displacement 32-bit

101

[ebp] + displacement 32-bit

110

[esi] + displacement 32-bit

111

[edi] + displacement 32-bit

Endereçamento em 64-bit

MOD 00

R/M
Endereçamento

0000

[rax/eax]

0001

[rcx/ecx]

0010

[rdx/edx]

0011

[rbx/ebx]

0100

SIB

0101

[rip/eip] + displacement 32-bit

0110

[rsi/esi]

0111

[rdi/edi]

1000

[r8/r8d]

1001

[r9/r9d]

1010

[r10/r10d]

1011

[r11/r11d]

1100

SIB

1101

[rip/eip] + displacement 32-bit

1110

[r14/r14d]

1111

[r15/r15d]

MOD 01

R/M
Endereçamento

0000

[rax/eax] + displacement 8-bit

0001

[rcx/ecx] + displacement 8-bit

0010

[rdx/edx] + displacement 8-bit

0011

[rbx/ebx] + displacement 8-bit

0100

SIB + displacement 8-bit

0101

[rbp/ebp] + displacement 8-bit

0110

[rsi/esi] + displacement 8-bit

0111

[rdi/edi] + displacement 8-bit

1000

[r8/r8d] + displacement 8-bit

1001

[r9/r9d] + displacement 8-bit

1010

[r10/r10d] + displacement 8-bit

1011

[r11/r11d] + displacement 8-bit

1100

SIB + displacement 8-bit

1101

[r13/r13d] + displacement 8-bit

1110

[r14/r14d] + displacement 8-bit

1111

[r15/r15d] + displacement 8-bit

MOD 10

R/M
Endereçamento

0000

[rax/eax] + displacement 32-bit

0001

[rcx/ecx] + displacement 32-bit

0010

[rdx/edx] + displacement 32-bit

0011

[rbx/ebx] + displacement 32-bit

0100

SIB + displacement 32-bit

0101

[rbp/ebp] + displacement 32-bit

0110

[rsi/esi] + displacement 32-bit

0111

[rdi/edi] + displacement 32-bit

1000

[r8/r8d] + displacement 32-bit

1001

[r9/r9d] + displacement 32-bit

1010

[r10/r10d] + displacement 32-bit

1011

[r11/r11d] + displacement 32-bit

1100

SIB + displacement 32-bit

1101

[r13/r13d] + displacement 32-bit

1110

[r14/r14d] + displacement 32-bit

1111

[r15/r15d] + displacement 32-bit

Byte SIB

Os endereçamentos com R/M 100 (em 32-bit e 64-bit) são os que usam o byte SIB (exceto MOD 11), que como já foi explicado anteriormente contém os campos Scale, Index e Base que são calculados de maneira equivalente a expressão:

base + index * scale

Onde o campo scale são os 2 primeiros bits, onde seu valor numérico é equivalente aos seguintes fatores de escala:

  • 00 - Não multiplica o index

  • 01 - Multiplica o index por 2

  • 10 - Multiplica o index por 4

  • 11 - Multiplica o index por 8

Devido ao o campo R/M é estendido em 1 bit no modo de 64-bit.

Já os campos index e base contém 3 bits cada e os mesmos armazenam o que serão usados. Os bits dos campos no byte seguem a ordem que o próprio nome sugere. Como em: SSIIIBBB.

opcode
Codificação dos registradores
prefixo REX
código dos registradores