Assembler nos tempos modernos
Conheça um pouco sobre a mais poderosa de todas as linguagens de programação

Certo, você chegou naquele ponto onde fica parecendo que há alguma coisa a mais a ser conhecida, sobre programação de computadores, mas não sabe bem o que é. Já ouviu pessoas sussurrando palavras como assembler, assembly, código de máquina e outros termos compucabalísticos, mas passou batido por todos eles. Notou até que as pessoas que mencionaram tais termos demonstraram nem mesmo elas terem conhecimento consistente sobre o que estavam falando, daí fugirem de perguntinhas básicas, do tipo: para que serve isso?

Então tá, chegou a hora de separar os meninos dos homens de verdade (em termos de programação, claro) e para isso criamos essa seção especial, no tópico programação. Mas antes os avisos de praxe: o que será mostrado aqui é feito por profissionais e não tente reproduzir em casa, sem a supervisão de um adulto.

Mais: se você ferrar o seu HD, detonar o bios do seu computador, derrubar um ônibus espacial ou simplesmente disparar à distância as bombas nucleares americanas, azar o seu. Eu avisei que era perigoso mexer com essa linguagem.

Dito isso, vamos em frente e tente responder honestamente a pergunta a seguir: você realmente sabe o que é um programa de computador e como ele funciona (memória, processador, etc)? Não precisa responder com um tratado de eletrônica digital, mas apenas simbolicamente.

Entendi: não sabe. Então vou explicar simbolicamente... O computador é formado basicamente pela memória e pelo processador. O tal processador é a máquina que faz a coisa toda funcionar; a memória nada mais é do que um monte de gavetas (com 8 bits cada uma).

Ele, o processador, pega um valor em uma dessas gavetas e interpreta-o como o código de uma instrução. Por exemplo: somar dois valores, contidos em duas outras gavetas. Ele identifica o endereço da primeira gaveta e pega o valor nela contido. Depois identifica o endereço da segunda gaveta, pega o valor nela e soma com o primeiro valor, colocando o resultado em algum lugar (outra gaveta, por exemplo).

Quem comanda isso é o relógio do computador, que tem mais utilidade do que simplesmente mostrar as horas na barra de tarefas do Windows. Estou falando do relógio interno, ou clock. Aquele valor que usamos para dizer o quão potente é nosso micro: 4Mhz, 12 Mhz, 800 Mhz, 1.5 Ghz e os modernosos 3.5 Ghz, indicam a velocidade com a qual o processador faz as coisas...

Tique, identifica o endereço; taque, pega o conteúdo; tique, identifica o segundo endereço; taque, soma o valor encontrado com o primeiro; tique, coloca o resultado em algum lugar.

Simples assim: quanto mais rápido for o relógio do seu micro, mais rápido o processador faz as coisas e conseqüentemente mais coisas ele pode fazer no mesmo intervalo de tempo. É por isso que você troca de micro todos os anos e já está de olho naquele processador de 4 Ghz que andam anunciando.

Certo, mas na prática, como isso funciona de verdade? Também é muito simples: o processador tem um pouco de memória interna, a qual damos o nome de registradores. Na verdade, não nos referimos a eles como endereços de memória, pois eles têm nomes. Nada sugestivos, como EBX, AH, SI, CH, AEX, etc. Mas depois que nos acostumamos com eles, tudo fica mais simples. Quando dizemos "pega um valor numa gaveta", na verdade estamos dizendo: "copia o valor de um endereço na memória para um determinado registrador".

Então vejamos como é a fisionomia de um registrador multiuso, pau para toda obra, bom e barato: o EAX. Trata-se de um registrador de 32 bits e se você não tem ainda intimidade com bits e bytes, dê uma lida na página especial Bit e Byte e depois volte aqui.

Preste atenção na figura acima. Note que cada quadradinho representa um bit, que por definição pode ser zero (0) ou um (1). Note ainda que EAX é o nome do registrador, quando queremos nos referir aos 32 bits de uma única vez, porém, se quisermos tratar apenas dos 16 bits menos significativos (do 0 ao 15), podemos usar o nome AX. Mais: se dentro desses 16 bits quisermos tratar dos 8 bits menos significativos (do 0 ao 7), podemos chamá-los de AL, ou, no caso dos 8 bits mais significativos (do 8 ao 15), AH (L de Low e H de High). Evidentemente que os bits, por representarem valores, são numerados da direita para a esquerda.

Então, dependendo do que estamos fazendo ou dos valores que queremos manipular, escolhemos que registrador usar. Por exemplo: somar 5 mais 3. Como são valores pequenos, podemos usar o registrador de 8 bits:

mov al,5 ;coloca o valor 5 no registrador
add al,3 ;soma 3 ao valor original

Ok, parece ser fácil. Mas como eu faço tudo isso?

Simples: no Delphi. É isso aí amigão! O Delphi possui, embutido nele, o melhor e mais poderoso compilador assembler que se tem notícia na face visível e invisível da terra, que é o Turbo Assembler da própria Borland. Daqui a pouco você vai sacar no que tudo isso implica.

Voltando à vaca fria: crie um form novo e coloque nele um botão qualquer. No evento onClick escreva o seguinte:

  procedure TForm1.SpeedButton1Click(Sender: TObject);
  begin
    asm
      mov al,5
      add al,3
    end;
  end; 

Notou só o grande barato? Você abre um bloco asm e tudo o que vier a seguir é o mais puro e cristalino assembler. "Mais melhor" que isso é impossível. Mas para ver de fato o que está acontecendo...

Primeiro, coloque um breakpoint na instrução mov al,5. Se nunca fez isso, basta dar um clique duplo naquela bolinha azul, que aparece à esquerda no fonte do programa. Isso significa que o programa irá ser interrompido naquele ponto. Execute-o e quando parar, abra a janela CPU: View>Debug Windows>CPU.

Bingo! Você está olhando para a alma do seu programa. Não há nem como ir mais fundo do que isso. Note, na janela maior, à esquerda, o ponto (breakpoint) onde o seu programa foi interrompido. Em negrito aparece a linha como você a digitou e em baixo dela o que o computador vai entender (assembly) dela. Mais ainda: está presente lá o endereço real da memória onde isso está acontecendo (00440F54h) e, pasmem os senhores, o código de máquina da instrução (B005).

Houve um tempo no qual nós programávamos escrevendo diretamente esse código na memória do micro. Bons tempos aqueles....

Voltando: B0 é o código da instrução que coloca o valor a seguir (05) no registrador AL e 80 C0 é o código da instrução que soma o valor a seguir (03) com esse mesmo registrador.

Agora olhe para a janela do meio (ao lado da janela maior). Você verá nela, marcado em cinca ou azul, o registrador EAX e o conteúdo original dele. Se executar linha a linha o programa (tecla F7) verá o valor 5 ser colocado nos 8 bits menos significativos e depois a soma com o valor 3. Caramuru, caramuru!!!!

Então é isso o tal do "assembly"? Pode crer que é simples assim. Trabalhoso, mas simples. Aí você pergunta, mas e o resto que aparece naquela janela? Certo, falemos de linguagens de programação...

Percebeu como seria complicado escrever os programas tendo que decorar o que cada código significa, ou que instrução ele representa? Nem no tempo da informática a carvão decorávamos todas as instruções. Só as mais importantes.

As linguagens de programação foram inventadas para isso mesmo: não ter que lembrar de nada (ou pelo menos de muita coisa). Assim escrevemos o nosso programa num padrão qualquer (a linguagem) e passamos esse "fonte" por um compilador. O compilador converte o texto nos seus respectivos códigos assembler. O Delphi faz isso, com o que escrevemos em object pascal. Os compiladores C, idem, idem.

Isso significa que você escreve uma linha no Delphi assim: for lin:= 0 to 100 do begin pode "assistir" em assembly como o compilador "programa" esse laço ou looping. Barbada, não é mesmo?

E mais, uma vez compilado o seu programa (escrito em Pascal, C, Basic, Sâscrito, Latim ou na estranha língua dos papuas da nova guiné), provavelmente (se os compiladores forem bons mesmo) eles se equivalerão. Então, da próxima vez que alguém lhe disser que jogos profissionais precisam ser escritos em C++, apenas dê um sorriso maroto e nem perca tempo tentando discutir com o "entendido", porque ele provavelmente não sabe do que está falando.

Mas, mas, mas... Acontece que nos primórdios da microinformática pessoal, os computadores saiam de fábrica com um interpretador Basic. Isso porque não existia software à venda e o usuário tinha que criar os seus próprios programas. O Basic é uma excelente linguagem, embora um pouco caótica. Mas o problema maior é que o programa era interpretado e não compilado, ou seja, dele existia apenas o código fonte e na hora da execução ele era compilado linha a linha. Trabalho dobrado e sujeito a muitos erros.

Ao mesmo tempo, todas as outras linguagens e principalmente o C, eram compiladas e portanto o resultado final acabava sendo muito mais eficiente e rápido. Daí para as pessoas relacionarem uma coisa com a outra... O problema é que os dogmas ficam, mesmo depois de cientificamente comprovada a besteira original, de onde eles surgiram.

Resta então a questão: se no final tudo fica do mesmo tamanho, então porque usar esta ou aquela linguagem? Por vários motivos e razões, dentre as quais, facilidade de compreensão e entendimento, poder de compilação e processamento das ferramentas disponíveis, biblioteca de rotinas e funções já prontas, testadas e comprovadas, etc.

Você pode dizer que criar jogos em C tem lá suas vantagens e uma delas é a grande quantidade de material técnico sobre o assunto. Também pode dizer que é melhor escrever logo em assembler, porque assim o código sai mais enxuto. Ou pode mesmo dizer que prefere escrever o jogo em Delphi porque as ferramentas e facilidades são excepcionais, incluindo aí poder usar assembler dentro do seu jogo, com um pé nas costas e assobiando o hino nacional, de trás para frente, em ré menor.

E por não fazer todo o programa em assembler? Porque dá muito trabalho. Gasta tempo e esforço que pode ser melhor aproveitado pesquisando sobre o tema e enredo do jogo, fazendo gráficos melhores, ou simplesmente divulgando mais o seu jogo.

OBS: Mas o meu amigo me disse que o nome certo da linguagem é "assembly" e não "assembler". Ele está certo. Assembler é o nome que damos ao compilador e não à linguagem. Ocorre que programadores da velha guarda, que escreviam seus programas em valores hexadecimais, eram eles próprios os compiladores: os programadores assembler. Quem passou por isso, ganhou o direito internacional de chamar a linguagem fundamental da forma que achar melhor. Assembler ou assembly, tanto faz.

Mas, se o seu amigo insistir no termo correto, deixe para lá, porque ele certamente nunca ouviu falar da época de ouro, na qual os programadores escovavam e poliam os bits um a um.

 
online