< Coluna em Fórum PCs >
|
||
06/03/2006
|
< Computadores XXVII: Mnemônicos > |
Neste ponto de nossa jornada você já dispõe de todo o necessário para desenvolver qualquer programa que rode em nossa UCP elementar: conhece a estrutura da UCP, sua forma de se comunicar com a MP e sabe de cor (ou não?) todos os dezesseis membros de seu limitado conjunto de instruções examinados detalhadamente nas duas últimas colunas. E já viu um exemplo de um programa completo, funcional, carregado na memória principal. Talvez até tenha “quebrado a cabeça” tentando descobrir o que o tal programeto faz (não é impossível, houve quem conseguisse). Mas, tendo ou não conseguido, certamente há de ter chegado a uma conclusão irretorquível: programar em linguagem de máquina é difícil pracacete abessa ou mais... Para os que não quiserem se dar ao trabalho de consultar as colunas anteriores aqui vai o programa em linguagem de máquina. Na coluna da esquerda, os endereços de cada posição de memória e na coluna da direita o conteúdo das respectivas posições. Dureza para entender, nénão?
Há uma razão para isso. “Linguagem”, segundo o dicionário Houaiss, é “qualquer meio sistemático de comunicar idéias ou sentimentos através de signos convencionais, sonoros, gráficos, gestuais etc.”. Ou seja: uma forma de comunicação. Máquinas se comunicam com máquinas usando números. Já humanos se comunicam com humanos usando palavras. Para um humano, “entender” a linguagem da máquina é tão difícil quanto para a máquina “entender” a linguagem dos humanos. Seria muito mais fácil se pudéssemos nos comunicar com a máquina usando palavras, cujos significados são muito mais fáceis de memorizar para nós, humanos. Desde que, naturalmente, houvesse uma forma de converter as palavras que nós humanos entendemos nos números que as máquinas “entendem”. Então cuidemos primeiro do que vem primeiro: substituir números por palavras. Depois veremos como fazer a máquina “entender” essas palavras. Tomemos uma instrução qualquer como exemplo. Digamos a instrução cujo código é (0001b) (o “b” final indicando que o número está expresso em binário, ou no sistema numérico posicional de base dois). O que ela faz? Examinando a descrição das instruções descobrimos que ela “executa um salto incondicional no fluxo do programa”. Ou seja: SALTA, independentemente do conteúdo do acumulador. Procuremos uma forma de exprimir isso usando uma palavra simples de tal modo que seja fácil lembrar o que faz a instrução apenas examinando a palavra. Que tal “SLTA”? (Neste ponto cabe um parênteses: é claro que eu poderia usar “SALTA”, ainda mais fácil de entender que “SLTA”, mas acontece que decidi padronizar em quatro o número de caracteres da palavra que representa a instrução apenas para combinar com o número de bits do código da instrução e facilitar minha tarefa de substituir um programa em código de máquina por seu correspondente em Assembly. Esta decisão foi pessoal e arbitrária e nada tem a ver com a verdadeira linguagem Assembly, que usa “palavras” de tamanhos diferentes. Eu somente pude adotá-la porque o número de instruções de nosso conjunto é pequeno, apenas dezesseis.) Sim, “SLTA” lembra “salta”, portanto fiquemos com ela. E como teremos outras instruções de salto (quando o conteúdo do acumulador for zero, positivo ou negativo, respectivamente), vamos começá-las todas com as letras “SLT” para facilitar a lembrança que se trata de uma instrução de salto. Para a instrução [0010b], salto no caso do conteúdo do acumulador ser zero, acrescentemos um “Z” (de “Zero”) e a “batizaremos” de “SLTZ”. O salto caso positivo (instrução 0011b) será “batizado” de “SLTP” acrescentando um “P” de “Positivo” e o salto caso negativo (instrução 0100b) será “SLTN”, recebendo o acréscimo do “N” de “Negativo”. Falta “batizar” apenas uma das instruções de controle de fluxo, aquela que pára o programa em seu final, interrompendo sua marcha (instrução 0000b). Que batizaremos de “ALTO” (como o comando militar que interrompe a marcha da soldadesca). O resultado é o conjunto de “nomes” abaixo listado: Instruções de controle de fluxo: {[0000] [00000000]} = ALTO {[0001] [endereço]} = SLTA [endereço] {[0010] [endereço]} = SLTZ [endereço] {[0011] [endereço]} = SLTP [endereço] {[0100] [endereço]} = SLTN [endereço] Mas, afinal, o que fizemos? Praticamente nada. Apenas substituímos quatro números por quatro letras. Ocorre que, na listagem de um programa, ao encontrar a instrução “SLTZ” fica muito mais fácil lembrar que ela promove um salto caso o acumulador contenha um zero que ao encontrar o número 0010. Coisas que facilitam a lembrança chamam-se “mnemônicos”. E isso nada tem a ver com informática, tem a ver com português mesmo, aqui está o Houaiss novamente que não me deixa mentir: “mnemônico: relativo à memória; ... que serve para desenvolver a memória e facilitar a memorização;... fácil de ser lembrado; de fácil memorização”. Por isso essas “palavras” usadas para substituir os códigos das instruções são conhecidas por “mnemônicos”. Ou seja: a linguagem Assembly usa mnemônicos em vez dos códigos numéricos da linguagem de máquina. E não há como negar que isso facilita muito a interpretação das listagens de programas. Vejamos as instruções de entrada e saída. A instrução (0101b), que lê um valor da ENTRADA padrão e o escreve no ACC chamaremos de “ENTR” e a (0110b) que envia o conteúdo do ACC para a SAÍDA padrão batizaremos de “SAID” (para respeitar o critério dos quatro caracteres). Ficaremos então com: Instruções de entrada/saída: {[0101] [00000000]} = ENTR {[0110] [00000000]} = SAID Para movimentar dados temos apenas três instruções. A (0111b), que “escreve o número de oito bits no ACC” receberá o mnemônico “ACCM” para lembrar de “acumulador” (algo me diz que tentando com um pouco mais de afinco eu conseguiria um mnemônico melhorzinho para esta). A instrução (1000b), que executa uma LEITURA de memória batizaremos de “LEIA” e a (1000b) que executa uma ESCRITA na memória de “ESCR”. O resultado é a relação abaixo: Instruções de movimentação de dados: {[0111] [valor]} = ACCM [valor] {[1000] [endereço]} = LEIA [endereço] {[1001] [endereço]} = ESCR [endereço] Agora, ficou fácil “batizar” as instruções matemáticas ou lógicas. Nem vou me dar ao trabalho de explicar o que elas fazem (e, se você não entender todas elas, provavelmente está lendo a série de colunas errada; como não quero perder leitores e o ibope desta série já não está lá essas coisas, por via das dúvidas vou ajudar um pouco: a primeira “incrementa” o acumulador e a segunda o “decrementa”; as demais ficam por sua conta, mas a quem não descobrir o que elas fazem recomendo cuidado para não sujar a testa na próxima vez que tomar sorvete). A lista fica: Instruções matemáticas e lógicas: {[1010] [00000000]} = INCR {[1011] [00000000]} = DECR {[1100] [endereço]} = SOMA [endereço] {[1101] [endereço]} = SUBT [endereço] {[1110] [endereço]} = MULT [endereço] {[1111] [endereço]} = DIVI [endereço] Pronto. Tudo o que fizemos até agora foi substituir quatro bits por quatro caracteres. Mas que diferença! Se eu encontrasse o código (1010b) em uma listagem muito provavelmente teria que recorrer a uma tabela para descobrir o que o programador pretendia com ele, mas se eu me deparar com o mnemônico “INCR” dificilmente deixarei de lembrar que tudo o que ele pretende é incrementar o valor do acumulador. Já facilitou um bocado. Veja como fica nosso programa substituindo os códigos das instruções por seus mnemônicos:
Muito mais fácil de entender, pois não? E, repare: ao contrário das linguagens de alto nível, em que um único comando pode ser desdobrado em dezenas, eventualmente centenas ou milhares de instruções em linguagem de máquina, nesta linguagem que estamos “inventando” (e que logo descobriremos que já foi inventada e se chama Assembly) existe uma correspondência biunívoca (ou seja, correspondência “de um para um”) entre os mnemônicos e os códigos de instrução. A cada mnemônico corresponde uma e apenas uma instrução e a cada instrução corresponde um e apenas um mnemônico. O que significa que, basicamente, programar em Assembly corresponde a substituir os códigos das instruções (em linguagem de máquina) por seus correspondentes mnemônicos (em Assembly). Mas apenas isso já é uma melhora e tanto. Basta comparar esta listagem aí de cima com a lá do início da coluna. Porém, para nosso programa se tornar um pouco mais compreensível ainda falta solucionar um problema cabeludo: batizar e endereçar as variáveis. Um conceito interessante que fica para a próxima coluna. B. Piropo |