# Saltos

Provavelmente você já sabe o que é um desvio de fluxo de código em uma linguagem de alto nível. Algo como uma instrução `if` que condicionalmente executa um determinado bloco de código, ou um `for` que executa várias vezes o mesmo bloco de código. Tudo isso é possível devido ao desvio do fluxo de código. Vamos a um pseudo-exemplo de um `if`:

```
1. Compare o valor de X com Y
2. Se o valor de X for maior, pule para 4.
3. Adicione 2 ao valor de X
4.
```

Repare que se a comparação no passo 1 der que o valor de X é maior, a instrução no passo 2 faz um desvio para o passo 4. Desse jeito o passo 3 nunca será executado. Porém caso a condição no passo 2 for falsa, isto é, o valor de X não é maior do que o valor de Y então o desvio não irá acontecer e o passo 3 será executado.

Ou seja o passo 3 só será executado sob uma determinada condição. Isso é um código condicional, isso é um `if`. Repare que o resultado da comparação no passo 1 precisa ficar armazenado em algum lugar, e este "lugar" é o registrador FLAGS.

### Salto não condicional

Antes de vermos um desvio de fluxo condicional vamos entender como é o próprio desvio de fluxo em si.\
Na verdade existem muito mais registradores do que os que eu já citei. E um deles é o registrador IP, sigla para *Instruction Pointer* (ponteiro de instrução). Esse registrador também acompanha o tamanho do barramento interno, assim como os registradores gerais:

| IP      | EIP     | RIP     |
| ------- | ------- | ------- |
| 16 bits | 32 bits | 64 bits |

Assim como o nome sugere o *Instruction Pointer* serve como um ponteiro para a próxima instrução a ser executada pelo processador. Desse jeito é possível mudar o fluxo do código simplesmente alterando o valor de IP, porém não é possível fazer isso diretamente com uma instrução como a `mov`.

Na arquitetura x86 existem as instruções de *jump*, salto em inglês, que alteram o valor de IP permitindo assim que o fluxo seja alterado. A instrução de *jump* não condicional, intuitivamente, se chama JMP. Esse desvio de fluxo é algo muito semelhante com a instrução `goto` da linguagem C, inclusive em boa parte das vezes o compilador converte o `goto` para meramente um JMP.

O uso da instrução JMP é feito da seguinte forma:

```nasm
jmp endereço
```

Onde o operando você pode passar um rótulo que o assembler irá converter para o endereço corretamente. Veja o exemplo na nossa PoC:

{% tabs %}
{% tab title="assembly.asm" %}

```nasm
bits 64

global assembly
assembly:
  mov eax, 555
  jmp .end

  mov eax, 333

.end:
  ret
```

{% endtab %}

{% tab title="main.c" %}

```c
#include <stdio.h>

int assembly(void);

int main(void)
{
  printf("Resultado: %d\n", assembly());
  return 0;
}
```

{% endtab %}
{% endtabs %}

A instrução na linha 8 nunca será executada devido ao JMP na linha 6.

{% hint style="info" %}
Repare que na linha 10 estamos usando um rótulo local que foi explicado no tópico sobre a [sintaxe do nasm](/assembly/a-base/sintaxe.md).
{% endhint %}

### Registrador FLAGS

O registrador FLAGS também é estendido junto ao tamanho do barramento interno. Então temos:

| FLAGS   | EFLAGS  | RFLAGS  |
| ------- | ------- | ------- |
| 16 bits | 32 bits | 64 bits |

Esse registrador, diferente dos registradores gerais, não pode ser acessado diretamente por uma instrução. O valor de cada **bit** do registrador é testado por determinadas instruções e são ligados e desligados por outras instruções. É testando o valor dos **bits** do registrador FLAGS que as instruções condicionais funcionam.

### Salto condicional

Os *jumps* condicionais, normalmente referidos como Jcc, são instruções que condicionalmente fazem o desvio de fluxo do código. Elas verificam os valores dos bits do registrador FLAGS e, com base nos valores, será decidido se o salto será tomado ou não. Assim como no caso do JMP as instruções Jcc também recebem como operando o endereço para onde devem tomar o salto **caso** a condição seja atendida. Se ela não for atendida então o fluxo de código continuará normalmente.

Eis a lista dos saltos condicionais mais comuns:

| Instrução | Nome estendido                       | Condição                   |
| --------- | ------------------------------------ | -------------------------- |
| JE        | **J**ump if **E**qual                | Pula se for igual          |
| JNE       | **J**ump if **N**ot **E**qual        | Pula se **não** for igual  |
| JL        | **J**ump if **L**ess than            | Pula se for menor que      |
| JG        | **J**ump if **G**reater than         | Pula se for maior que      |
| JLE       | **J**ump if **L**ess or **E**qual    | Pula se for menor ou igual |
| JGE       | **J**ump if **G**reater or **E**qual | Pula se for maior ou igual |

{% hint style="info" %}
O nome Jcc para se referir aos saltos condicionais vem do prefixo 'J' seguido de 'cc' para indicar uma condição, que é o formato da nomenclatura das instruções.

Exemplo: JLE -- 'J' prefixo, 'LE' condição (*Less or Equal*)

Essa mesma nomenclatura também é usada para as outras instruções condicionais, como por exemplo CMOVcc.
{% endhint %}

A maneira mais comum usada para setar as *flags* para um salto condicional é a instrução CMP. Ela recebe dois operandos e compara o valor dos dois, com base no resultado da comparação ela seta as *flags* corretamente. Agora um exemplo na nossa PoC:

{% tabs %}
{% tab title="assembly.asm" %}

```nasm
bits 64

global assembly
assembly:
  mov eax, 0

  mov rbx, 7
  mov rcx, 5  
  cmp rbx, rcx
  jle .end

  mov eax, 1
.end:
  ret
```

{% endtab %}

{% tab title="main.c" %}

```c
#include <stdio.h>

int assembly(void);

int main(void)
{
  printf("Resultado: %d\n", assembly());
  return 0;
}
```

{% endtab %}
{% endtabs %}

Na linha 10 temos um *Jump if Less or Equal* para o rótulo local `.end`, e logo na linha anterior uma comparação entre RBX e RCX. Se o valor de RBX for menor ou igual a RCX, então o salto será tomado e a instrução na linha 12 não será executada. Desta forma temos algo muito parecido com o `if` no pseudocódigo abaixo:

```c
eax = 0;
rbx = 7;
rcx = 5;
if(rbx > rcx){
  eax = 1;
}
return;
```

Repare que a condição para o código ser executado é exatamente o oposto da condição para o salto ser tomado. Afinal de contas a lógica é que caso o salto seja tomado o código **não** será executado.

{% hint style="info" %}
Experimente modificar os valores de RBX e RCX, e também teste usando outros Jcc.
{% endhint %}


---

# 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/a-base/saltos.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.
