# Flags do processador

O registrador EFLAGS contém *flags* que servem para indicar três tipos de informações diferentes:

* **Status** -- Indicam o resultado de uma operação aritmética.
* **Control** -- Controlam alguma característica de execução do processador.
* **System** -- Servem para configurar ou indicar alguma característica do *hardware* relacionado a execução do código ou do sistema.

Enquanto o RFLAGS de 64 bits contém todas as mesmas *flags* de EFLAGS sem nenhuma nova. Todos os 32 bits mais significativos do RFLAGS estão reservados e sem nenhum uso atualmente. Observe a figura abaixo retirada do [Intel Developer's Manual Vol. 1](https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-software-developers-manual-volume-1-basic-architecture), mostrando uma visão geral do bits de EFLAGS:

![](https://2466397120-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lif0YmrEB3G3dh1VxSC%2F-LlILBIJzoyZmkujf9rb%2F-LlIQoWa28g6C0p2NFnN%2FCaptura%20de%20tela%20de%202019-08-02%2014-32-05.png?alt=media\&token=2a0ef142-8cac-49c4-b824-86bbef9ad283)

### Status Flags

Instruções que fazem operações aritméticas modificam as *status flags* conforme o valor do resultado da operação. São instruções como `ADD`, `SUB`, `MUL` e `DIV` por exemplo.

Porém um detalhe que é interessante saber é que existem duas instruções que normalmente são utilizadas para definir essas *flags* para serem usadas junto com uma instrução condicional. Elas são: `CMP` e `TEST`. A instrução `CMP` nada mais é do que uma instrução que faz a mesma operação aritmética de subtração que `SUB` porém sem modificar o valor dos operandos.

Enquanto `TEST` faz uma operação *bitwise AND* (E bit a bit) também sem modificar os operandos. Ou seja, o mesmo que a instrução `AND`. Veja a tabela abaixo com todas as *status flags*:

<table data-header-hidden><thead><tr><th width="150">Bit</th><th width="150">Nome</th><th width="150">Sigla</th><th width="276.1538461538462">Descrição</th></tr></thead><tbody><tr><td>Bit</td><td>Nome</td><td>Sigla</td><td>Descrição</td></tr><tr><td>0</td><td>Carry Flag</td><td>CF</td><td>Setado se uma condição de <em>Carry</em> ou <em>Borrow</em> acontecer no bit mais significativo do resultado. Basicamente indica o <em>overflow</em> de um valor não-sinalizado.</td></tr><tr><td>2</td><td>Parity Flag</td><td>PF</td><td>​Setado se o byte menos significativo do resultado conter um número par de bits ligados (1).</td></tr><tr><td>4</td><td>Auxiliary Carry Flag</td><td>AF</td><td>Setado se uma condição de <em>Carry</em> ou <em>Borrow</em> acontecer no bit 3 do resultado.</td></tr><tr><td>6</td><td>Zero Flag</td><td>ZF</td><td>Setado se o resultado for zero.</td></tr><tr><td>7</td><td>Sign Flag</td><td>SF</td><td>Setado para o mesmo valor do bit mais significativo do resultado (<a href="https://pt.wikipedia.org/wiki/Bit_mais_significativo">MSB</a>). Onde 0 indica um valor positivo e 1 indica um valor negativo.</td></tr><tr><td>11</td><td>Overflow Flag</td><td>OF</td><td>Setado se o resultado não tiver o sinal esperado da operação aritmética. Basicamente indica o <em>overflow</em> de um número sinalizado.</td></tr></tbody></table>

{% hint style="info" %}
*Carry*, ou carrinho/transporte, é o que a gente conhece no Brasil como "vai um"  em uma operação aritmética de adição. *Borrow* é o mesmo princípio porém em aritmética de subtração, em linguagem coloquial chamado de "pegar emprestado".
{% endhint %}

Dentre essas *flags* somente CF pode ser modificada diretamente e isso é feito com as seguintes instruções:

```nasm
stc  ; (Set CF)        Seta o valor da Carry Flag
clc  ; (Clear CF)      Zera o valor da Carry Flag
cmc  ; (coMplement CF) Inverte o valor da Carry Flag
```

### Control Flags

| Bit | Nome           | Sigla | Descrição                                                                                                                 |
| --- | -------------- | ----- | ------------------------------------------------------------------------------------------------------------------------- |
| 10  | Direction Flag | DF    | Controla a direção para onde as instruções de *string* (`MOVS`, `SCAS`, `STOS`, `CMPS` e `LODS`) irão decorrer a memória. |

Se DF estiver setada as instruções de *string* irão decrementar o valor do(s) registrador(es). Se estiver zerada ela irá incrementar, que é o valor padrão para essa *flag*.

```nasm
std  ; (Set DF)    Seta o valor da Direction Flag
cld  ; (Clear DF)  Zera o valor da Direction Flag
```

{% hint style="warning" %}
Caso sete o valor dessa *flag* é importante que a zere novamente em seguida. Código compilado normalmente espera que por padrão essa *flag* esteja zerada. Comportamentos imprevistos podem acontecer caso você não a zere depois de usar.
{% endhint %}

### System Flags

As *system flags* podem ser lidas por qualquer programa porém somente o sistema operacional pode modificar seus valores (exceto ID). Abaixo irei falar somente das *flags* que nos interessam saber por agora.

<table data-header-hidden><thead><tr><th width="150">Bit</th><th width="150">Nome</th><th width="150">Sigla</th><th width="284.1538461538462">Descrição</th></tr></thead><tbody><tr><td>Bit</td><td>Nome</td><td>Sigla</td><td>Descrição</td></tr><tr><td>8</td><td>Trap Flag</td><td>TF</td><td>Se setada o processador irá executar as instruções do programa passo a passo. Nesse modo o processador dispara uma <em>exception</em> para cada instrução executada. É normalmente usada para depuração de código.</td></tr><tr><td>9</td><td>Interrupt enable Flag</td><td>IF</td><td>Controla a resposta do processador para interrupções que podem ser ignoradas (interrupções mascaráveis).</td></tr><tr><td>12-13</td><td>I/O Privilege Level field</td><td>IOPL</td><td>Indica o nível de acesso para a comunicação direta com o <em>hardware</em> (operações de I/O) do programa atual.</td></tr><tr><td>14</td><td>Nested Task flag</td><td>NT</td><td>Se setada indica que a tarefa atual está vinculada com uma tarefa anterior. Essa <em>flag</em> controla o comportamento da instrução <code>IRET</code>.</td></tr><tr><td>16</td><td>Resume Flag</td><td>RF</td><td>Se setada as <em>exceptions</em> disparadas pelo processador são temporariamente desabilitadas na instrução seguinte. Geralmente usada por depuradores.</td></tr><tr><td>17</td><td>Virtual-8086 Mode flag</td><td>VM</td><td>Em <em>protected mode</em> se essa <em>flag</em> for setada o processador entra em modo Virtual-8086.</td></tr><tr><td>21</td><td>Identification flag</td><td>ID</td><td>Se um processo conseguir setar ou zerar essa <em>flag</em>, isto indica que o processador suporta a instrução <code>CPUID</code>.</td></tr></tbody></table>

{% hint style="info" %}
IOPL na verdade não é uma *flag* mas sim um campo de 2 bits que indica o nível de privilégio de acesso para operações de I/O a partir da porta física do processador.
{% endhint %}

As instruções abaixo podem ser utilizadas para modificar o valor de IF:

```nasm
sti  ; (Set IF)   Seta o valor da Interrupt Flag
cli  ; (Clear IF) Zera o valor da Interrupt Flag
```

### FLAGS (16-bit)

Em *real mode* dentre as *system flags* somente TF e IF existem e não dependem de qualquer tipo de privilégio para serem modificadas, qualquer software executado pelo processador tem permissão irrestrita às *flags*.
