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

![](/files/-LlIQoWa28g6C0p2NFnN)

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mentebinaria.gitbook.io/assembly/aprofundando-em-assembly/flags-do-processador.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
