> For the complete documentation index, see [llms.txt](https://mentebinaria.gitbook.io/assembly/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mentebinaria.gitbook.io/assembly/apendices/codigo-de-maquina/modr-m-e-sib.md).

# ModR/M e SIB

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`&#x20;
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 [opcode](/assembly/apendices/codigo-de-maquina/opcode.md). 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.

{% content-ref url="/pages/Q6aigICLm6yM6yWbWHtH" %}
[Codificação dos registradores](/assembly/apendices/codigo-de-maquina/codificacao-dos-registradores.md)
{% endcontent-ref %}

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`.

{% hint style="info" %}
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.
{% endhint %}

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

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[BX+SI]</code></td></tr><tr><td>001</td><td><code>[BX+DI]</code></td></tr><tr><td>010</td><td><code>[BP+SI]</code></td></tr><tr><td>011</td><td><code>[BP+DI]</code></td></tr><tr><td>100</td><td><code>[SI]</code></td></tr><tr><td>101</td><td><code>[DI]</code></td></tr><tr><td>110</td><td>displacement 16-bit</td></tr><tr><td>111</td><td><code>[BX]</code></td></tr></tbody></table>

#### MOD 01

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[BX+SI]</code> + displacement 8-bit</td></tr><tr><td>001</td><td><code>[BX+DI]</code> + displacement 8-bit</td></tr><tr><td>010</td><td><code>[BP+SI]</code> + displacement 8-bit</td></tr><tr><td>011</td><td><code>[BP+DI]</code> + displacement 8-bit</td></tr><tr><td>100</td><td><code>[SI]</code> + displacement 8-bit</td></tr><tr><td>101</td><td><code>[DI]</code> + displacement 8-bit</td></tr><tr><td>110</td><td><code>[BP]</code> + displacement 8-bit</td></tr><tr><td>111</td><td><code>[BX]</code> + displacement 8-bit</td></tr></tbody></table>

#### MOD 10

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[BX+SI]</code> + displacement 16-bit</td></tr><tr><td>001</td><td><code>[BX+DI]</code> + displacement 16-bit</td></tr><tr><td>010</td><td><code>[BP+SI]</code> + displacement 16-bit</td></tr><tr><td>011</td><td><code>[BP+DI]</code> + displacement 16-bit</td></tr><tr><td>100</td><td><code>[SI]</code> + displacement 16-bit</td></tr><tr><td>101</td><td><code>[DI]</code> + displacement 16-bit</td></tr><tr><td>110</td><td><code>[BP]</code> + displacement 16-bit</td></tr><tr><td>111</td><td><code>[BX]</code> + displacement 16-bit</td></tr></tbody></table>

### Endereçamento em 32-bit

#### MOD 00

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[eax]</code></td></tr><tr><td>001</td><td><code>[ecx]</code></td></tr><tr><td>010</td><td><code>[edx]</code></td></tr><tr><td>011</td><td><code>[ebx]</code></td></tr><tr><td>100</td><td>SIB</td></tr><tr><td>101</td><td>displacement 32-bit</td></tr><tr><td>110</td><td><code>[esi]</code></td></tr><tr><td>111</td><td><code>[edi]</code></td></tr></tbody></table>

#### MOD 01

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[eax]</code> + displacement 8-bit</td></tr><tr><td>001</td><td><code>[ecx]</code> + displacement 8-bit</td></tr><tr><td>010</td><td><code>[edx]</code> + displacement 8-bit</td></tr><tr><td>011</td><td><code>[ebx]</code> + displacement 8-bit</td></tr><tr><td>100</td><td>SIB + displacement 8-bit</td></tr><tr><td>101</td><td><code>[ebp]</code> + displacement 8-bit</td></tr><tr><td>110</td><td><code>[esi]</code> + displacement 8-bit</td></tr><tr><td>111</td><td><code>[edi]</code> + displacement 8-bit</td></tr></tbody></table>

#### MOD 10

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>000</td><td><code>[eax]</code> + displacement 32-bit</td></tr><tr><td>001</td><td><code>[ecx]</code> + displacement 32-bit</td></tr><tr><td>010</td><td><code>[edx]</code> + displacement 32-bit</td></tr><tr><td>011</td><td><code>[ebx]</code> + displacement 32-bit</td></tr><tr><td>100</td><td>SIB + displacement 32-bit</td></tr><tr><td>101</td><td><code>[ebp]</code> + displacement 32-bit</td></tr><tr><td>110</td><td><code>[esi]</code> + displacement 32-bit</td></tr><tr><td>111</td><td><code>[edi]</code> + displacement 32-bit</td></tr></tbody></table>

### Endereçamento em 64-bit

{% hint style="info" %}
Devido ao [prefixo REX](/assembly/apendices/codigo-de-maquina/prefixo-rex.md) o campo R/M é estendido em 1 bit no modo de 64-bit.
{% endhint %}

#### MOD 00

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>0000</td><td><code>[rax/eax]</code></td></tr><tr><td>0001</td><td><code>[rcx/ecx]</code></td></tr><tr><td>0010</td><td><code>[rdx/edx]</code></td></tr><tr><td>0011</td><td><code>[rbx/ebx]</code></td></tr><tr><td>0100</td><td>SIB</td></tr><tr><td>0101</td><td><code>[rip/eip]</code> + displacement 32-bit</td></tr><tr><td>0110</td><td><code>[rsi/esi]</code></td></tr><tr><td>0111</td><td><code>[rdi/edi]</code></td></tr><tr><td>1000</td><td><code>[r8/r8d]</code></td></tr><tr><td>1001</td><td><code>[r9/r9d]</code></td></tr><tr><td>1010</td><td><code>[r10/r10d]</code></td></tr><tr><td>1011</td><td><code>[r11/r11d]</code></td></tr><tr><td>1100</td><td>SIB</td></tr><tr><td>1101</td><td><code>[rip/eip]</code> + displacement 32-bit</td></tr><tr><td>1110</td><td><code>[r14/r14d]</code></td></tr><tr><td>1111</td><td><code>[r15/r15d]</code></td></tr></tbody></table>

#### MOD 01

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>0000</td><td><code>[rax/eax]</code> + displacement 8-bit</td></tr><tr><td>0001</td><td><code>[rcx/ecx]</code> + displacement 8-bit</td></tr><tr><td>0010</td><td><code>[rdx/edx]</code> + displacement 8-bit</td></tr><tr><td>0011</td><td><code>[rbx/ebx]</code> + displacement 8-bit</td></tr><tr><td>0100</td><td>SIB + displacement 8-bit</td></tr><tr><td>0101</td><td><code>[rbp/ebp]</code> + displacement 8-bit</td></tr><tr><td>0110</td><td><code>[rsi/esi]</code> + displacement 8-bit</td></tr><tr><td>0111</td><td><code>[rdi/edi]</code> + displacement 8-bit</td></tr><tr><td>1000</td><td><code>[r8/r8d]</code> + displacement 8-bit</td></tr><tr><td>1001</td><td><code>[r9/r9d]</code> + displacement 8-bit</td></tr><tr><td>1010</td><td><code>[r10/r10d]</code> + displacement 8-bit</td></tr><tr><td>1011</td><td><code>[r11/r11d]</code> + displacement 8-bit</td></tr><tr><td>1100</td><td>SIB + displacement 8-bit</td></tr><tr><td>1101</td><td><code>[r13/r13d]</code> + displacement 8-bit</td></tr><tr><td>1110</td><td><code>[r14/r14d]</code> + displacement 8-bit</td></tr><tr><td>1111</td><td><code>[r15/r15d]</code> + displacement 8-bit</td></tr></tbody></table>

#### MOD 10

<table><thead><tr><th width="150">R/M</th><th>Endereçamento</th></tr></thead><tbody><tr><td>0000</td><td><code>[rax/eax]</code> + displacement 32-bit</td></tr><tr><td>0001</td><td><code>[rcx/ecx]</code> + displacement 32-bit</td></tr><tr><td>0010</td><td><code>[rdx/edx]</code> + displacement 32-bit</td></tr><tr><td>0011</td><td><code>[rbx/ebx]</code> + displacement 32-bit</td></tr><tr><td>0100</td><td>SIB + displacement 32-bit</td></tr><tr><td>0101</td><td><code>[rbp/ebp]</code> + displacement 32-bit</td></tr><tr><td>0110</td><td><code>[rsi/esi]</code> + displacement 32-bit</td></tr><tr><td>0111</td><td><code>[rdi/edi]</code> + displacement 32-bit</td></tr><tr><td>1000</td><td><code>[r8/r8d]</code> + displacement 32-bit</td></tr><tr><td>1001</td><td><code>[r9/r9d]</code> + displacement 32-bit</td></tr><tr><td>1010</td><td><code>[r10/r10d]</code> + displacement 32-bit</td></tr><tr><td>1011</td><td><code>[r11/r11d]</code> + displacement 32-bit</td></tr><tr><td>1100</td><td>SIB + displacement 32-bit</td></tr><tr><td>1101</td><td><code>[r13/r13d]</code> + displacement 32-bit</td></tr><tr><td>1110</td><td><code>[r14/r14d]</code> + displacement 32-bit</td></tr><tr><td>1111</td><td><code>[r15/r15d]</code> + displacement 32-bit</td></tr></tbody></table>

### 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

Já os campos **index** e **base** contém 3 bits cada e os mesmos armazenam o [código dos registradores](/assembly/apendices/codigo-de-maquina/codificacao-dos-registradores.md) que serão usados. Os bits dos campos no byte seguem a ordem que o próprio nome sugere. Como em: `SSIIIBBB`.
