UFU / FACOM / Autran Macêdo/ Anilton |
Introdução à Ciência da Computação (INF64)/Informática Básica(GAG009)
Programa de
Computador
Afinal,
por que um computador "funciona"?
Bem
esta é uma pergunta cuja resposta envolve toda Ciência
da Computação. Mas sendo sucinto, um computador
(hardware) "funciona" porque um programa (software)
está inserido nele. Esse programa implementa uma seqüência
de instruções que deve ser seguida pelo computador para
a realização de um objetivo.
Um programa que é fundamental ao computador é o sistema operacional (SO). Esse programa é o responsável por tornar "fácil" o uso do computador. Uma vez "carregado" no computador, é o SO que torna possível o uso de componentes como o teclado, o vídeo, a unidade de DVD, a porta USB, e também o uso de outros programas como editores de texto, planilhas e navegadores da Internet.
Em um computador que segue a arquitetura de von Neumann, qualquer programa, para ser executado, necessita estar armazenado na memória. Somente depois de carregado na memória é que o processador (que inclui a Unidade de Controle e a Unidade Lógica e Aritmética) consegue executar as instruções do programa na seqüência especificada.
Mas
como se faz um programa?
Um programa é
uma seqüência de instruções que deve ser
seguida para se atingir um objetivo. Em geral, esse objetivo consiste
da apresentação da solução para um
problema. Por exemplo, "preciso de um programa que calcule a
soma de dois números naturais quaisquer".
Inicialmente devemos estudar e entender o problema (neste caso, o
problema é bem simples, mas a maioria dos problemas
interessantes são bastante complexos). Em seguida devemos
escrever um algoritmo.
Similarmente a um programa, um
algoritmo é uma seqüência de instruções
que deve ser seguida para se atingir um objetivo. Só que o
algoritmo é um "texto" para um ser humano seguir.
(Uma receita de bolo é um algoritmo: o problema que esse
algoritmo procura resolver é "como
transformar os ingredientes do bolo em bolo - de preferência
saboroso".)
Um exemplo de algoritmo para o problema da soma de números,
mencionado anteriormente, é apresentado abaixo:
1)
Seja a um número Natural qualquer
2)
Seja b um número Natural qualquer
3)
Repita os passos 4 e 5, enquanto b>0
4)
a = a + 1
5)
b = b - 1
6)
Mostre a
O algoritmo acima resolve o problema. Além
disso, ele foi escrito de uma forma inteligível ao ser humano.
Isto é, um ser humano é capaz de seguir e realizar os
passos do algoritmo. Mas para esse algoritmo ser executado por um
computador (de von Neumann), precisamos traduzi-lo para a linguagem
binária. Além disso, é necessário que
essa tradução esteja em conformidade com o conjunto
de instruções do computador alvo.
Como
traduzir um algoritmo em linguagem binária?
Nos
primórdios da computação digital, a tradução
de algoritmos para a linguagem binária era realizada
manualmente. Isto é, o programador escrevia o algoritmo em
termos de zeros e uns, conforme a organização
(quantidade de registradores,
por exemplo) e o conjunto de instruções da máquina
alvo.
Vamos considerar um computador hipotético dos primórdios da computação digital e chamá-lo de CHipo0012. O CHipo0012 possui apenas 1 (um) registrador de dados (utilizado pela Unidade Lógica e Aritmética - ULA) e o conjunto de instruções constante na Tabela 1.
Tabela 1: conjunto de instruções do CHipo0012.
Código |
Instrução |
---|---|
0 |
Finaliza o Programa |
1 |
Carrega <mem> no registrador de dados |
2 |
Carrega <input> na memória |
3 |
Incrementa de 1 o conteúdo do registrador de dados |
4 |
Decrementa de 1 o conteúdo do registrador de dados |
5 |
Apresenta <mem> |
6 |
Salta para um endereço de memória |
7 |
Compara se registrador de dados > 0, se sim salta <mem> |
8 |
Carrega conteúdo registrador de dados na <mem> |
As instruções
apresentadas acima são aquelas que o Chipo conseguia executar
(na época - década de 60). Portanto, um programa para
essa máquina deveria consitir de uma seqüência
adequada dessas instruções. Uma ilustração
do CHipo0012 é apresentado na Figura 1.
Figura
1: ilustração do CHipo0012 (um computador hipotético
dos primórdios da computação digital - década
60)
Os botões verdes representavam os oito bits de um byte. Quando se pressionava um dos botões, esse botão ficava aceso, indicando que o bit correspondente estava ligado. Esses botões eram utilizados para se inserir instruções e dados na memória do computador. A inserção se dava quando se pressionava o botão INPUT.
Quando todo o programa estava na memória, o botão RUN era pressionado. O programa então "tomava conta" do computador (naquela época os SOs eram ainda muito incipientes). O resultado da computação era apresentado pelos botões verdes (juntamente com o indicador OUTPUT aceso) ou quando muito numa impressora. Quando o programa terminava o indicador END ficava aceso. Finalmente, o botão CLEAR era pressionado quando se desejava "esvaziar" a memória.
O programador, com base no
conjunto de instruções, tinha de condificar as
instruções para o Chipo num determinado formato. O
formato da instrução é similar ao apresentado na
Figura 2.
Figura
2: formato da instrução do computador CHipo 0012.
Com
esse formato, a cada 16 bits havia uma instrução na
memória do computador. O código da instrução
(a ser executada) deveria estar expressa nos 4 (quatro) bits mais
significativos, os quatro bits seguintes não tinham uso, e os
8 (oito) bitas restantes eram utilizados para especificação
de emndereço. Por exemplo, se tivéssemos que transferir
o conteúdo do endereço 184 de memória para o
registrador de dados, o programador deveria digitar no painel do
CHipo a seguinte instrução
0001 0000 1011
1000
Observe que 0001 (dos 4 bits mais significativos)
corresponde à representação binária do
código da instrução 1 (vide Tabela 1), que
realiza transferência do conteúdo de um endereço
de memória para o registrador de dados. O endereço em
questão está especificado nos 8 (oito) bits menos
siginifcativos.
Vejamos um outro exemplo.
Suponha que o número 3 está arqmzenado no endereço
de memória 192. Quais instruções que o
programador deveria inserir no computador para que esse endereço
passasse a conter o número 2? As instruções
poderiam ser as seguintes:
0001 0000 1100 0000
coloca o 3 (que está no endereço
192) no registrador
0100 0000 0000 0000
decrementa o conteúdo do
registrador
1000 0000 1100 0000 coloca
o conteúdo do registrador (que agora é 2) de volta ao
endereço 192
Pois bem, para implementar o algoritmo de soma de números naturais apresentado inicialmente, um programador deveria escrever um programa similar ao da Tabela 2.
Tabela 2: programa em linguagem binária que implementa o algoritmo de soma de dois números naturais
End.Mem. |
Instrução |
Comentário |
---|---|---|
0 |
0010 0000 1101 0000 |
Carrega INPUT na mem.(208) |
16 |
0010 0000 1110 0000 |
Carrega INPUT na mem.(224) |
32 |
0001 0000 1110 0000 |
Carrega o conteúdo da mem.(224) no reg. |
48 |
0110 0000 1010 0000 |
Salta para mem.(160) |
64 |
0001 0000 1101 0000 |
Carrega o conteúdo da mem.(208) no reg. |
80 |
0011 0000 0000 0000 |
Incrementa o conteúdo do reg. |
96 |
1000 0000 1101 0000 |
Coloca o conteúdo do reg. na mem.(208) |
112 |
0001 0000 1110 0000 |
Carrega o conteúdo da mem.(224) no reg. |
128 |
0100 0000 0000 0000 |
Decrementa o conteúdo do reg. |
144 |
1000 0000 1110 0000 |
Coloca o conteúdo do reg. na mem.(224) |
160 |
0111 0000 01000 0000 |
Se o conteúdo do reg.>0, salta para mem.(64) |
176 |
0101 0000 1101 0000 |
Mostra conteúdo da mem.(208) |
192 |
0000 0000 0000 0000 |
Fim |
208 |
? |
Dado qualquer digitado pelo usuário |
224 |
? |
Dado qualquer digitado pelo usuário |
Portanto, o programador dos
primórdios tinha de conhecer a origanização da
máquina e o seu conjunto de instruções. Além
disso, também tinha de programar em binário, que por si
só era uma tarefa suscetível a erro e de difícil
depuração. E se você acha que o CHipo não
existiu, veja a Figura 3. Trata-se de um computador da empresa HP
modelo 2100, no qual o CHipo foi inspirado.
Figura
3: imagem do computador HP2100
retirada da página Computer
History Museum Old "Visible Storage" de Ed Thelen.
Ainda
hoje é assim que se transforma algoritmo em liguagem
binária?
Não. Hoje em dia
escolhemos uma linguagem de programação,
codificamos o algoritmo nessa linguagem, e obtemos o código
binário correspondente por meio de um outro programa, chamado
compilador.
Uma linguagem de programação
é uma linguagem projetada para especificar programas de
computador. A primeira linguagem de programação foi a
linguagem Assembly. Essa linguagem permitia que o programador
utilizasse símbolos que representavam as instruções
da máquina. Por exemplo, suponha que o programador tivesse que
"carregar o conteúdo do endereço de memória
224 no registrador de dados". Ao invés do programador
escrever na linguagem binária a instrução
0001
0000 1101 0000
ele poderia escrever
load 224
Um
avanço formidável. Agora, o programador não
tinha de se preocupar com a conversão correta para a linguagem
binária. Essa conversão estava a cargo de um outro
programa que converteria a expressão "load 224" na
instrução binária correspondente.
Depois do Assembly, outras propostas de linguagem de programação surgiram, de modo que hoje existe uma plêiade de linguagens, para os mais variados tipos de problemas.
Finalmente, o compilador. O compilador de uma linguagem é um programa cujo objetivo é ler um programa escrito nessa linguagem e gerar a linguagem binária correspondente para a máquina alvo. Por exemplo, o gcc é o compilador da linguagem C para SOs baseados em GNU/Linux.