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 JrApó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