Desenvolvimento - C/C++

A inteligência do if

Estava outro dia filosofando com meu amigo sobre o funcionamento do conceito mais poderoso em programação de computadores: o if.

por Wanderley Caloni Jr



Estava outro dia filosofando com meu amigo sobre o funcionamento do conceito mais poderoso em programação de computadores: o if. E me perguntava como que o computador consegue tomar uma decisão a partir de uma comparação. É o tipo de problema cuja resposta parece óbvia, mas enquanto você não se aprofunda no tema, nunca fica satisfeito de fato (mesmo sabendo a teoria).

Após quebrar a cabeça por algum tempo, encontrei uma solução no mínimo interessante:

Computadores lêem e escrevem na memória, e é isso. Uma instrução é uma leitura de bits da memória para o circuito lógico que altera o estado da máquina. Uma comparação é uma escrita em flags depois da entrada ter passado por um filtro de portas lógicas. Um salto é a escrita do endereço da próxima instrução no program counter. Quando uma função é chamada seus parâmetros e o endereço de retorno são escritos na pilha (uma área da memória). Para retornar, uma instrução lê o endereço da pilha e o coloca no program counter.

Sendo assim, confirmado que Von Neumann e Turing ainda não morreram, nada mais justo supor que um if é um salto automaticamente calculado através do resultado de uma comparação feita imediatamente antes. Isso traduzindo em código de alto nível:

#include <stdio.h>

void True()
{
   printf("Verdadeiro\n");
}

void False()
{
   printf("Falso\n");
}


typedef void (*Jump)();
Jump If[2] = { False, True };

int main(int argc, char* argv[])
{
   If[2 > 3]();
   If[3 > 2]();
}

Eis um código que executa um salto condicional sem o uso do if que vem de fábrica. Na verdade, o if emulado acima constitui conceitualmente o que imagino que ocorra nas entranhas de um PC. Imagino, pois não fui a fundo o suficiente para vasculhar os documentos da Intel. Para mim, a mágica foi desvendada. O deslumbramento é que continua...

A nível de assembly, a comparação se baseia na diferença dos valores, se a mesma é zero ou se existe sobra de valor, se for zero, é porque os valores são iguais, se sobrou, diferentes, então para se definir qual é o maior, é analizado o sinal do resultado da subtração, este fica armazenado em um bit reservado para tal fim.

O Jump é executado após a subtração/comparação dos valores, assim, se o salto é executado, é alterado o endereço que o registrador que aponta para o código a carregar para o endereço informado no código executável/fonte.

Ex:

...
mov ax, 0x01 # Carga do valor 0x01 no registrador ax
mov bx, 0x02 # Carga do valor 0x02 no registrador bx
cmp ax, bx   # Cálculo da comparação executado
jz  0xAF05   # <i>Jump Zero:</i> Verificação do resultado do cálculo, 
             # salta se os valores são iguais 
             # resultado do cálculo deve ser zero para ocorrer o salto
# ou

jnz 0xAF05   # <i>Jump Not Zero</i>: Verifica o resultado do cálculo e 
             # salta se os valores não são iguais
             # resultado do cálculo diferente de zero
...

Após a execução, se ocorreu o salto, o registrador ponteiro de código do processador é direcionado para o endereço 0xAF05 e carrega o código executável a partir deste, que por sequência é executado, se o mesmo não ocorreu, a execução segue normalmente como se a instrução de jump não existisse.

Artigo original: Caloni.com.br

Complementação de assembly por: Rudinei Felipetto

Wanderley Caloni Jr

Wanderley Caloni Jr