Sie sind auf Seite 1von 10

Introdução

m computador digital é uma máquina que pode resolver problemas para as pessoas executando instruções que lhe são dadas. Uma

U seqüência de instruções que descreve como realizar certa tarefa é denominada programa. Os circuitos eletrônicos de cada
computador podem reconhecer e executar diretamente um conjunto limitado de instruções simples, e,
para que os programas possam ser executados, todos devem antes ser convertidos em instruções. Essas instruções básicas raramente são
muito mais complicadas do que:
Some dois números.
Verifique um número para ver se ele é zero.
Copie dados de uma parte da memória do computador para outra.

Juntas, as instruções primitivas de um computador formam uma linguagem com a qual as pessoas podem se comunicar com ele.
Essa linguagem é denominada linguagem de máquina. Quem projeta um novo computador deve decidir quais instruções incluir em sua
linguagem de máquina. Em geral, os projetistas tentam fazer com que as instruções primitivas sejam as mais simples possíveis,
coerentes com os requisitos de utilização e desempenho idealizados para o computador, de modo a reduzir a complexidade e o custo da
eletrônica necessária. Como a maioria das linguagens de máquina é bem simples, todos acham difícil e entediante usá-Ia.
Com o passar do tempo, essa simples observação resultou em uma maneira de estruturar computadores como uma série de
abstrações, cada uma acumulando-se àquela que lhe lhe precede. Assim, a complexidade pode ser dominada e sistemas de computação
podem ser projetados de modo estruturado, sistemático. Denominamos essa abordagem organização estruturada de computadores - foi
esse o nome que demos a nosso livro. Na seção seguinte descreveremos o que significa esse termo. Logo após, comentaremos alguns
desenvolvimentos históricos, o estado atual da tecnologia e exemplos importantes.

1.1 Organização estruturada de computadores


Como já mencionamos, existe uma grande lacuna entre o que é conveniente para as pessoas e o que é conveniente para
computadores. As pessoas querem fazer X, mas os computadores só podem fazer Y, o que dá origem a um problema. O objetivo deste
livro é explicar como esse problema pode ser resolvido.

1.1.1 Linguagens, níveis e máquinas reais


o problema pode ser abordado de duas maneiras; ambas envolvem projetar um novo conjunto de instruções que seja mais
conveniente para as pessoas usarem do que o conjunto de instruções que já vem embutido na máquina. Juntas, essas novas instruções
também formam uma linguagem, que denominaremos LI, exatamente como as instruções de máquina formam uma linguagem, que
denominaremos LO. As duas abordagens são diferentes no modo como os programas escritos em LI são executados pelo computador
que, afinal, só pode executar programas escritos em sua linguagem de máquina, LO.
Um método para executar um programa escrito em LI é primeiro substituir cada instrução escrita no programa por uma seqüência
equivalente de instruções em LO. O programa resultante consiste inteiramente em instruções LO. Então o computador executa o novo
programa LO em vez do antigo programa, LI. Essa técnica é denominada tradução.
A outra técnica é escrever um programa em LO que considere programas em LI como dados de entrada e os execute examinando
cada instrução por vez e executando diretamente a seqüência equivalente de instruções LO. Essa técnica não requer a

1
2 geração prévia de um novo programa em LO. Ela é denominada interpretação e o programa que a executa é chamado
interpretador.
Tradução e interpretação são semelhantes. Em ambos os métodos o computador executa instruções em LI que realizam
seqüências equivalentes de instruções em LO. A diferença é que, na tradução, todo o programa LI é antes convertido para
um programa LO; o programa LI é descartado e então o novo programa LO é carregado na memória do computador e
executado. Durante a execução é o programa LO recém-gerado que está rodando no computador e quem o está controlando.
Na interpretação, após o exame e a decodificação de cada instrução LI, ela é executada imediatamente. Nenhum
programa traduzido é gerado. Aqui, o interpretador está no controle do computador. Para ele, o programa LI é apenas uma
coleção de dados. Os dois métodos são muito usados e cresce cada vez mais a utilização de uma combinação de ambos.
Em vez de pensar em termos de tradução e interpretação, muitas vezes é mais simples imaginar a existência de um
computador hipotético ou máquina real cuja linguagem de máquina seja LI. Vamos denominar essa máquina real MI (e
vamos denominar MO a máquina real correspondente a LO). Se fosse bem barato construir uma máquina como essa não
haveria nenhuma necessidade de ter linguagem LO ou uma máquina que executasse programas em LO. As pessoas poderiam
simplesmente escrever seus programas em LI e fazer com que o computador os exe
cutasse diretamente.
Mesmo que a máquina real com linguagem LI fosse muito cara ou complicada de construir com circuitos eletrônicos,
as pessoas ainda poderiam escrever programas para ela. Esses programas poderiam ser interpretados ou traduzidos por um
programa escrito em LO que pudesse ser executado diretamente pelo computador existente. Em outras palavras, seria
possível escrever programas para máquinas reais, exatamente como se elas existissem na realidade.
Para que a tradução e a interpretação sejam práticas, as linguagens LO e LI não devem ser 'muito' diferentes. Essa
limitação muitas vezes quer dizer que LI, embora melhor do que LO, ainda assim estará longe de ser ideal para a maioria
das aplicações. O resultado talvez seja desanimador à luz do propósito original da criação de LI -livrar o programador da
carga de ter de expressar algoritmos em uma linguagem mais adequada a máquinas do que a pessoas. Contudo, a situação
não é sem esperanças.
A abordagem óbvia é inventar um outro conjunto de instruções mais dirigido a pessoas e menos a máquinas do que LI.
Esse terceiro conjunto também forma uma linguagem que denominaremos L2 (e com máquina real M2). As pessoas podem
escrever programas em L2 exatamente como se de fato existisse uma máquina real com linguagem de máquina L2. Esses
programas podem ser traduzidos para LI ou executados por um interpretador escrito em LI.
A invenção de toda uma série de linguagens, cada uma mais conveniente do que suas antecessoras, pode continuar
indefinidamente até que, por fim, se chegue a uma adequada. Cada linguagem usa a antecessora como base, de modo que
podemos considerar um computador que use essa técnica como uma série de camadas ou níveis, um
sobre o outro, como mostra a Figura 1.1. A linguagem ou nível que fica mais embaixo é a mais simples e a que fica mais em
cima é a mais sofisticada.
Existe uma relação importante entre uma linguagem e uma máquina real. Cada máquina tem uma linguagem de
máquina, que consiste em todas as instruções que a máquina pode executar. Na verdade, a máquina define uma linguagem.
De modo semelhante, uma linguagem define uma máquina - a saber, a máquina que pode executar todos os programas
escritos na linguagem. Claro que pode ser muito complicado e muito caro construir uma máquina definida por uma certa
linguagem diretamente com base em circuitos eletrônicos, porém nada nos impede de imaginá-Ia. Uma máquina cuja
linguagem de máquina é C ou C++ ou Java seria realmente complexa, mas fácil de construir usando a tecnologia existente
hoje. Porém, há uma boa razão para não construir um computador como

Programas em Ln são
interpretados por um
Máquina real Mn, com interpretador que roda em
Nível n
linguagem de máquina Ln uma máquina de nível
inferior, ou são traduzidos
para a linguagem de
máquina de uma máquina
de nível inferior
Nível 3

Programas em L2 são
interpretados por interpretadores
que
Figura 1.1 Máquina rodam em M1 ou MO, ou são
Nível 2 traduzidos para L 1 ou LO
multinivel.
Programas em L 1 são
interpretados por um interpretador
que roda em MO, ou são traduzidos
Nível 1 para LO

Programas em LO podem ser


executados diretamente pelos
Nivela circuitos eletrônicos
esse: seu custo não seria eficiente em comparação com outras técnicas. Não basta apenas ser viável: um projeto prático 3
também deve ter um custo aceitável.
Em certo sentido, um computador com n níveis pode ser considerado como n máquinas reais diferentes, cada uma com
uma linguagem de máquina diferente. Usaremos os termos 'nível' e 'máquina real' indiferentemente. Somente programas
escritos em linguagem LO podem ser executados diretamente pelos circuitos eletrônicos, sem a necessidade de tradução ou
interpretação intervenientes. Programas escritos em LI, L2, ..., Ln devem ser interpretados por um interpretador que roda em
um nível mais baixo ou traduzidos para uma outra linguagem correspondente a um nível mais baixo.
Uma pessoa que escreve programas para a máquina real de nível n não precisa estar ciente dos interpretadores e
tradutores subjacentes. A estrutura da máquina garante que esses programas sejam executados, de uma maneira ou de outra.
Não há nenhum interesse real se eles são executados passo a passo por um interpretador que, por sua vez, também é
executado por um outro interpretador, ou se são executados diretamente pelos circuitos eletrônicos. O resultado é o mesmo
em ambos os casos: os programas são executados.
A maioria dos programadores que usam uma máquina de nível n está interessada apenas no nível superior, aquele que
menos se assemelha à linguagem de máquina que está no nível mais inferior. Todavia, quem se interessa em entender como
um computador realmente funciona deve estudar todos os níveis. Quem projeta novos computadores, ou novos níveis (isto é,
novas máquinas reais), também deve estar familiarizado com níveis que não sejam apenas o superior. Os conceitos e as
técnicas da construção de máquinas como uma série de níveis e os detalhes destes são o principal assunto deste livro.

1.1.2 Máquinas multiníveis contemporâneas


A maioria dos computadores modernos consiste em dois ou mais níveis. Existem máquinas com até seis níveis, como
mostra a Figura 1.2. O nível O, na parte inferior, é o verdadeiro hardware da máquina. Seus circuitos executam os
programas em linguagem de máquina de nível 1. Para não deixar nada de lado, devemos mencionar a existência de mais um
outro nível abaixo de nosso nível O. Esse nível, que não é mostrado na Figura 1.2 porque pertence ao domínio da engenharia
de eletricidade (e, portanto, está fora do escopo deste livro), é denominado nível de dispositivo. Nesse nível, o projetista vê
transistores individuais, que são os elementos de nível mais baixo para projetistas de computadores. Se perguntarmos como
é o funcionamento interno de um transistor, entraremos na área da física do estado sólido.
No nível mais baixo que estudaremos, o nível lógico digital, os objetos interessantes são denominados portas. Embora
construídas com componentes analógicos, como transistores, as portas podem ser modeladas com precisão como
dispositivos digitais. Cada porta tem uma ou mais entradas digitais (sinais que representam O ou 1) e computa como saída
alguma função simples dessas entradas, como E (AND) ou OU (OR). Cada porta é composta de, no máximo, um punhado
de transistores. Um pequeno número de portas pode ser combinado para formar uma memória de 1 bit, que pode armazenar
um O ou um 1. As memórias de 1 bit podem ser combinadas em grupos de, por exemplo, 16,32 ou 64 para formar
registradores. Um registrador pode conter de um único número binário até algum valor máximo. Portas também podem ser
combinadas para formar o próprio mecanismo principal de computação. Examinaremos portas e o nível lógico digital com
mais detalhes no Capítulo 3.
O próximo nível é o nível de microarquitetura. Nesse nível vemos, normalmente, um conjunto de 8 a 32 registradores
que formam uma memória local e um circuito denominado ALU (Arithmetic Logic Unit), ou ULA (Unidade Lógica e
Aritmética), que é capaz de executar operações aritméticas simples. Os registradores são conectados à ALU para formar um
caminho de dados através do qual os dados transitam. A operação básica do

Nívei 5 Nível de linguagem orientado a problemas

Tradução (compilador)

Nível 4 Nível de linguagem de montagem (assembly)

Tradução (assemblet'j

Nível 3 Nível do sistema operacional da máquina


Figura 1.2
Computador de seis níveis. O método de Interpretação parcial (sistema operacional)
suporte para cada nível está indicado abaixo
Nível 2 Nível de arquitetura de conjunto de instruções
dele (junto com o nome do programa de
suporte).
Interpretação (microprograma) ou execução direta

Nível 1 Nível de microarquitetura

Hardware

Nível O Nível lógico digital


...

4 caminho de dados consiste em selecionar um ou dois registradores, fazendo com que a ALU efetue algo com eles (por
exemplo, some-os) e armazene o resultado em algum registrador.
Em algumas máquinas a operação do caminho de dados é controlada por um programa denominado microprograma.
Em outras, ela é controlada diretamente por hardware. Nas três primeiras edições deste livro, denominávamos este nível de
'nível de microprogramação' porque, no passado, ele era quase sempre um interpretador de software. Visto que agora o
caminho de dados costuma ser, de modo parcial, controlado diretamente por hardware, mudamos o nome nesta edição para
retratar esse fato.
Em máquinas nas quais o caminho de dados é controlado por software, o microprograma é um interpretador para as
instruções no nível 2. Ele busca, examina e executa instruções uma por uma, usando o caminho de dados para fazê-lo. Por
exemplo, no caso de uma instrução ADD (SOME), a instrução seria buscada, seus operandos, localizados e trazidos para
dentro do registrador, a soma seria calculada pela ALU e, por fim, o resultado seria enviado de volta ao lugar a que
pertence. Em uma máquina com controle incorporado do caminho de dados, ocorreriam etapas semelhantes, mas sem um
programa explícito armazenado para controlar a interpretação das instruções do nível 2.
No nível 2 temos o que denominaremos nível de Arquitetura do Conjunto de Instruções (ISA
Instruction Set Architecture), ou nível ISA. Todo fabricante de computadores publica um manual para cada um dos
computadores que vende, intitulado 'Manual de Referência de Linguagem de Máquina' ou 'Princípios de Operação do
Western Wombat Model lOOX Computer', ou algo parecido. Na verdade, esses manuais tratam do nível ISA, e não dos
níveis subjacentes. Quando descrevem o conjunto de instruções da máquina, estão de fato descrevendo as instruções
executadas por interpretação pelo microprograma ou pelos circuitos de execução do hardware. Se um fabricante de
computadores fornecer dois interpretadores para uma de suas máquinas, os quais interpretam dois níveis ISA diferentes, ele
terá de fornecer dois manuais de referência de linguagem de máquina, um para cada interpretador.
O próximo nível em geral é híbrido. Grande parte das instruções em sua linguagem também está no nível ISA. (Não
há nenhuma razão por que uma instrução que aparece em um nível não possa estar presente também em outros.) Além
disso, há um conjunto de novas instruções, uma organização diferente da memória, a capacidade de executar dois ou mais
programas ao mesmo tempo e vários outros aspectos. Há mais variações entre projetos de nível 3 do que entre os de nível 1
ou nível 2.
As novas facilidades adicionadas ao nível 3 são executadas por um interpretador que roda no nível 2, o qual tem sido
denominado historicamente sistema operacional. Essas instruções de nível 3, idênticas às do nível 2, são executadas
diretamente pelo microprograma (ou controle incorporado), e não pelo sistema operacional. Em outras palavras, algumas
das instruções do nível 3 são interpretadas pelo sistema operacional e outras são interpretadas diretamente pelo
microprograma. É isso que 'híbrido' quer dizer. Neste livro denominaremos esse nível de nível de máquina de sistema
operacional.
Há uma ruptura fundamental entre os níveis 3 e 4. Os três níveis mais baixos não são projetados para utilização do
programador médio, de nível caseiro. Ao contrário, são dirigidos primariamente à execução dos interpretadores e tradutores
necessários para dar suporte aos níveis mais altos. Esses interpretadores e tradutores são escritos por pessoas denominadas
programadores de sistemas, que se especializam em projetar e implementar novas máquinas reais. Os níveis 4 e superiores
são dirigidos ao programador de aplicações que tem um problema a resolver.
Uma outra mudança que ocorre no nível 4 é o método de suporte dos níveis mais altos. Os níveis 2 e 3 são sempre
interpretados. Em geral, mas nem sempre, os níveis 4 e 5 são apoiados por tradução.
Uma outra diferença entre os níveis 1,2 e 3, por um lado, e níveis 4, 5 e superiores, por outro, é a natureza da
linguagem fornecida. As linguagens de máquina dos níveis 1, 2 e 3 são numéricas. Programas nessas linguagens consistem
de uma longa série de números que é muito boa para máquinas, mas ruim para pessoas. A partir do nível 4, as linguagens
contêm palavras e abreviações cujo significado as pessoas entendem.
O nível 4, nível da linguagem de montagem (assembly), na realidade é uma forma simbólica para uma das linguagens
subjacentes. Esse nível fornece um método para as pessoas escreverem programas para os níveis 1,2 e 3 em uma forma que
não seja tão desagradável quanto as linguagens de máquina real em si. Programas em linguagem de montagem são primeiro
traduzidos para linguagem de nível 1, 2 ou 3, e em seguida interpretados pela máquina real ou real adequada. O programa
que realiza a tradução é denominado assembler.
O nível 5 habitualmente consiste em linguagens projetadas para ser usadas por programadores de aplicações que
tenham um problema a resolver. Essas linguagens costumam ser denominadas linguagens de alto nível. Existem
literalmente centenas delas. Algumas das mais conhecidas são C, C++, Java, LISP e Prolog. Programas escritos nessas
linguagens em geral são traduzidos para nível 3 ou nível 4 por tradutores conhecidos como compiladores, embora às vezes
sejam interpretados, em vez de traduzidos. Programas em Java, por exemplo, costumam ser primeiro traduzidos para uma
linguagem semelhante à ISA denominada 'código de bytes Java' ou 'bytecode Java', que é então interpretada.
Em alguns casos, o nível 5 consiste em um interpretador para o domínio de uma aplicação específica, como
matemática simbólica. Ele fornece dados e operações para resolver problemas nesse domínio em termos que pessoas
versadas nele possam entendê-lo com facilidade.
Resumindo, o aspecto fundamental a lembrar é que computadores são projetados como uma série de níveis, cada um
construído sobre seus antecessores. Cada nível representa uma abstração distinta na qual estão presentes diferentes objetos e
operações. Por projetarmos e analisarmos computadores desse modo, por enquanto podemos dispensar detalhes irrelevantes
e assim reduzir um assunto complexo em algo mais fácil de entender.
o conjunto de tipos de dados, operações e características de cada nível é denominado arquitetura. A arquitetura trata 5
dos aspectos que são visíveis ao usuário daquele nível. Características que o programador vê, como a quantidade de
memória disponível, são parte da arquitetura. Aspectos de implementação, como o tipo de tecnologia usado para
implementar a memória, não são parte da arquitetura. O estudo sobre como projetar as partes de um sistema de computador
que sejam visíveis para os programadores é denominado arquitetura de computadores. Na prática, contudo, arquitetura de
computadores e organização de computadores significam essencialmente a mesma coisa.

1.1.3 Evolução de máquinas multiniveis


Para colocar as máquinas multiníveis sob certa perspectiva, examinaremos brevemente seu desenvolvimento histórico,
mostrando como o número e a natureza dos níveis evoluíram ao longo dos anos. Programas escritos em uma verdadeira
linguagem de máquina (nível 1) de um computador podem ser executados diretamente pelos circuitos eletrônicos (nível O)
do computador sem nenhum interpretador ou tradutor interveniente. Esses circuitos eletrônicos, junto com a memória e
dispositivos de entrada/saída, formam o hardware do computador. O hardware consiste em objetos tangíveis - circuitos
integrados, placas de circuito impresso, cabos, fontes de energia, memórias e impressoras - em vez de idéias abstratas,
algoritmos ou instruções.
O software, entretanto, consiste em algoritmos (instruções detalhadas que dizem como fazer algo) e suas
representações no computador, o que chamamos de programas. Os programas podem ser armazenados em disco rígido, disco
flexível, CD-ROM, ou outros meios, mas a essência do software é o conjunto de instruções que compõe os programas, e não
o meio físico no qual estão gravados.
Nos primeiros computadores, a fronteira entre hardware e software era nítida. Com o tempo, no entanto, essa fronteira
ficou bastante indistinta, primordialmente por causa da adição, remoção e fusão de níveis à medida que os computadores
evoluíam. Hoje em dia, muitas vezes é difícil distingui-Ia (Vahid, 2003). Na verdade, um tema central deste livro é

Hardware e software são logicamente equivalentes.


Qualquer operação executada por software também pode ser embutida diretamente no hardware, de preferência após
ela ter sido suficientemente bem entendida. Como observou Karen Panetta Lentz: "Hardware é apenas software petrificado".
Claro que o contrário é verdadeiro: qualquer instrução executada em hardware também pode ser simulada em software. A
decisão de colocar certas funções em hardware e outras em software é baseada em fatores como custo, velocidade,
confiabilidade e freqüência de mudanças esperadas. Há poucas regras rigorosas e imutáveis para determinar que X deva ser
instalado no hardware e Y deva ser explicitamente programado. Essas decisões mudam com as tendências econômicas, com
a demanda e com a utilização de tecnologias de computadores.

A invenção da microprogramação
Os primeiros computadores digitais, na década de 1940, tinham só dois níveis: o nível ISA, no qual era feita toda a
programação, e o nível lógico digital que executava esses programas. Os circuitos do nível lógico digital eram complicados,
difíceis de entender e montar, e não confiáveis.
Em 1951, Maurice Wilkes, pesquisador da Universidade de Cambridge, sugeriu projetar um computador de três níveis
para simplificar drasticamente o hardware (Wilkes, 1951). Essa máquina deveria ter um interpretador embutido, imutável (o
microprograma), cuja função fosse executar programas de nível ISA por interpretação. Como agora o hardware só teria de
executar microprogramas, que tinham um conjunto limitado de instruções, em vez de programas de nível ISA, cujos
conjuntos de instruções eram muito maiores, seria necessário um número menor de circuitos eletrônicos. Uma vez que, na
época, os circuitos eletrônicos eram compostos de válvulas eletrônicas, tal simplificação prometia reduzir o número de
válvulas e, portanto, aumentar a confiabilidade (isto é, o número de falhas por dia).
Poucas dessas máquinas de três níveis foram construídas durante a década de 1950. Outras tantas foram construídas
durante a década de 1960. Em tomo de 1970, a idéia de interpretar o nível ISA por um microprograma, em vez de
diretamente por meios eletrônicos, era dominante. Todas as principais máquinas da época a usavam.

A invenção do sistema operacional


Naqueles primeiros anos, grande parte dos computadores era 'acessível a todos', o que significava que o programador
tinha de operar a máquina pessoalmente. Ao lado de cada máquina havia uma planilha de utilização. Um programador que
quisesse executar um programa assinava a planilha e reservava um período de tempo, digamos, quarta-feira, das 3 às 5 da
manhã (muitos programadores gostavam de trabalhar quando a sala onde a máquina estava instalada ficava tranqüila).
Quando chegava seu horário, o programador se dirigia à sala da máquina com um pacote de cartões perfurados de 80
colunas (um meio primitivo de entrada de dados) em uma das mãos e um lápis bem apontado na outra. Ao chegar à sala do
computador, ele I gentilmente levava até a porta o programador que lá estava antes dele e tomava posse da máquina.

1. 'Ele' deve ser entendido como 'ele ou ela' em todo este livro.
6
Se quisesse executar um programa em FORTRAN o programador devia seguir as seguintes etapas:
1. Ele se dirigia ao armário onde era mantida a biblioteca de programas, retirava o grande maço verde rotu
lado 'compilador FORTRAN' , colocava-o na leitora de cartões e apertava o botão START.

2. Então colocava seu programa FORTRAN na leitora de cartões e apertava o botão CONTINUE. O progra
ma era lido pela máquina.

3. Quando o computador parava, ele lia seu programa FORTRAN em um segundo momento. Embora alguns
compiladores exigissem apenas uma passagem pela entrada, muitos requeriam duas ou mais. Para cada
passagem, era preciso ler um grande maço de cartões.

4. Por fim, a tradução se aproximava da conclusão. Era comum o programador ficar nervoso perto do final porque, se o compilador encontrasse um erro no programa, o
programador tinha de corrigi-lo e começar todo o processo novamente. Se não houvesse nenhum erro, o compilador perfurava em cartões o programa traduzido para
linguagem de máquina.
5. Então o programador colocava o programa em linguagem de máquina na leitora de cartões, junto com o
maço da biblioteca de sub-rotina, e lia ambos.
6. O programa começava a executar. Quase sempre não funcionava e parava inesperadamente no meio. Em geral, o programador mexia um pouco nas chaves de controle e
observava as luzes do console durante alguns instantes. Se tivesse sorte, conseguiria descobrir qual era o problema e corrigir o erro. Em seguida, voltava ao armário onde
estava guardado o grande e verde compilador FORTRAN e começava tudo de novo. Se não tivesse tanta sorte, imprimia o conteúdo da memória, denominado descarga
(dump) de memória, e o levava para casa a fim de estudá-lo.
Esse procedimento, com pequenas variações, foi o normal em muitos centros de computação durante anos. Ele forçava
os programadores a aprender como operar a máquina e o que fazer quando ela parava, o que acontecia com freqüência. A
máquina costumava ficar ociosa enquanto as pessoas carregavam cartões pela sala afora ou coçavam as respectivas cabeças
tentando descobrir por que seus programas não estavam funcionando adequadamente.
Perto de 1960 as pessoas tentaram reduzir o desperdício de tempo automatizando o trabalho do operador. Um
programa denominado sistema operacional era mantido no computador todo o tempo. O programador produzia certos
cartões de controle junto com o programa, que eram lidos e executados pelo sistema operacional. A Figura 1.3 apresenta
uma amostra de serviço (job) para um dos primeiros sistemas operacionais de ampla utilização, o FMS (FORTRAN Monitor
System), no IBM 709.
O sistema operacionallia o cartão *JOB e usava a informação nele contida para finalidades de contabilidade. (O
asterisco era usado para identificar cartões de controle, para que eles não fossem confundidos com cartões de programa e de
dados.) Depois o sistema lia o cartão *FORTRAN, que era uma instrução para carregar o compilador FORTRAN com base
em uma fita magnética. Então o programa era lido para a máquina e compilava pelo programa FORTRAN. Quando o
compilador terminava, devolvia o controle ao sistema operacional, que então lia o cartão *DATA. Isso era uma instrução
para executar o programa traduzido usando como dados os cartões que vinham após o cartão *DATA.
Embora o sistema operacional fosse projetado para automatizar o trabalho do operador (daí seu nome), foi também o
primeiro passo para o desenvolvimento de uma nova máquina real. O cartão *FORTRAN podia ser considerado como uma
instrução virtual 'compilar programa'.
De modo semelhante, o cartão *DATA podia ser considerado uma instrução virtual 'executar programa'. Um nível que
contivesse apenas duas instruções não era lá um grande nível, mas já era um começo.
Nos anos subseqüentes, os sistemas operacionais tomaram-se cada vez mais sofisticados. Novas instruções, facilidades
e características foram adicionadas ao nível ISA até que ele começou a parecer um novo nível. Algumas das instruções desse
novo nível eram idênticas às instruções do nível ISA, mas outras, em particular as instruções de entrada/saída, eram
completamente diferentes. As novas instruções começaram a ficar conhecidas como macros de sistema operacional ou
chamadas do supervisor. Agora o termo usual é chamada do sistema.

*JOB, 5494, BARBARA


*XEQ
*FORTRAN

Programa
FORTRAN

Figura 1.3
Amostra de serviço Uob) para
*DAT
o sistema operacional FMS. A

Cartões
de dados

*END
Sistemas operacionais também se desenvolveram de outras maneiras. Os primeiros liam maços de cartões e imprimiam
a saída na impressora de linha. Essa organização era conhecida como sistema batch. Normalmente havia uma espera de
várias horas entre o horário em que um programa entrava na máquina e o horário em que os resultados ficavam prontos. Era
difícil desenvolver software nessas circunstâncias.
No início da década de 1960, pesquisadores do Dartmouth College, do MIT e de outros lugares desenvolveram
sistemas operacionais que permitiam a vários programadores se comunicarem diretamente com o computador. Esses
sistemas tinham terminais remotos conectados ao computador central por linhas telefônicas. O computador era
compartilhado por muitos usuários. Um programador podia digitar um programa e obter os resultados impressos quase
imediatamente em seu escritório, na garagem de sua casa ou onde quer que o terminal estivesse localizado. Esses sistemas
eram denominados sistemas de tempo compartilhado (timesharing).
Nosso interesse em sistemas operacionais está nas partes que interpretam as instruções e características presentes no
nível 3 e que não estão presentes no nível ISA, em vez de nos aspectos de compartilhamento de tempo. Embora não vamos
destacar o fato, você deve ter sempre em mente que sistemas operacionais fazem mais do que apenas interpretar
características adicionadas ao nível ISA.

Migração de funcionalidade para microcódigo


Assim que a microprogramação se tomou comum (em 1970), os projetistas perceberam que podiam acrescentar novas
instruções apenas ampliando o microprograma. Em outras palavras, eles podiam acrescentar 'hardware' (novas instruções de
máquina) por programação. Essa revelação levou a uma explosão virtual de conjuntos de instruções de máquina, porque os
projetistas competiam uns com os outros para produzir conjuntos de instruções maiores e melhores. Muitas dessas instruções
não eram essenciais no sentido de que seu efeito podia ser conseguido com facilidade pelas instruções existentes, embora às
vezes fossem um pouco mais velozes do que uma seqüência de instruções já existente. Por exemplo, muitas máquinas
tinham uma instrução INC (INCrement) que adicionava 1 a um número. Como essas máquinas também tinham uma
instrução geral ADD, não era necessário ter uma instrução especial para adicionar 1 (ou 720, se fosse o caso). Contudo, a
INC normalmente era um pouco mais rápida que a ADD, e por isso era inserida.
Por essa razão, muitas outras instruções foram adicionadas ao microprograma. Entre elas as mais freqüentes eram:
1. Instruções para multiplicação e divisão de inteiros.
2. Instruções aritméticas para ponto flutuante.
3. Instruções para chamar e sair de procedimentos.
4. Instruções para acelerar laços (looping).
5. Instruções para manipular cadeias de caracteres.

Além do mais, assim que os projetistas de máquinas perceberam como era fácil acrescentar novas instruções,
começaram a procurar outras características para adicionar a seus microprogramas.
Eis alguns exemplos desses acréscimos:
1. Características para acelerar cálculos que envolvessem vetores (indexação e endereçamento indireto).
2. Características para permitir a movimentação de programas na memória após o início da execução (faci
lidades de relocação).
3. Sistemas de interrupção que avisavam o computador tão logo uma operação de entrada ou saída estivesse
concluída.
4. Capacidade para interromper um programa e iniciar outro com um pequeno número de instruções (comu
tação de processo).
5. Instruções especiais para processar arquivos de áudio, imagem e multimídia.

Inúmeras outras características e facilidades também foram acrescentadas ao longo dos anos, em geral para acelerar
alguma atividade particular.

Eliminação da microprogramação
Os microprogramas engordaram durante os anos dourados da microprogramação (décadas de 1960 e 1970) e também
tendiam a ficar cada vez mais lentos à medida que se tomavam mais volumosos. Por fim, alguns pesquisadores perceberam
que, eliminando o microprograma, promovendo uma drástica redução no conjunto de instruções e fazendo com que as
instruções restantes fossem executadas diretamente - isto é, controle do caminho de dados por hardware -, as máquinas
podiam ficar mais rápidas. Em certo sentido, o projeto de computadores fechou um círculo completo, voltando ao modo
como era antes de Wilkes inventar a microprogramação.
Mas a roda continua girando. Programas Java em geral são executados por compilação para uma linguagem
intermediária (bytecode Java) e depois pela interpretação dessa linguagem intermediária.
O objetivo dessa discussão é mostrar que a fronteira entre hardware e software é arbitrária e está sempre mudando. O
software de hoje pode ser o hardware de amanhã, e vice-versa. Além do mais, as fronteiras entre os vários níveis também
são fluidas. Do ponto de vista do programador, o modo como uma instrução é implementada
não é importante, exceto, talvez, no que se refere à sua velocidade. Uma pessoa que esteja programando no nível ISA pode
usar a instrução 'multiplicar' desse nível como se fosse uma instrução de hardware sem ter de se preocupar com ela ou até
mesmo sem saber se ela é, na verdade, uma instrução de hardware. O hardware de alguém é o software de outrem.
Voltaremos a todos esses tópicos mais adiante neste livro.

1.2 Marcos da arquitetura de computadores


Durante a evolução do computador digital moderno foram projetadas e construídas centenas de diferentes tipos de
computadores. Grande parte já foi esquecida há muito tempo, mas alguns causaram um impacto significativo sobre idéias
modernas. Nesta seção vamos apresentar um breve esboço de alguns dos principais desenvolvimentos históricos para
entender melhor como chegamos onde estamos agora. Nem é preciso dizer que esta seção apenas passa por alto os pontos
de maior interesse e deixa muita coisa de fora. A Tabela 1.1 apresenta algumas máquinas que marcaram época e
que serão discutidas nesta seção. Slater (1987) é uma boa referência de consulta para quem quiser material histórico
adicional sobre as pessoas que inauguraram a era do computador. Biografias curtas e belas fotos em cores, de autoria de
Louis Fabian Bachrach, de alguns dos principais fundadores da era do computador são apresentadas no livro de arte de
Morgan (1997).
Ano
Tabela 1.1 Alguns marcos no desenvolvimento do computador digital moderno.

Nome Construido por Comentários

1834 Máquina analítica Babbage Primeira tentativa de constnlir um computador digital


1936 ZI Zuse Primeira máquina de calcular com relés
1943 COLOSSUS Governo britânico Primeiro computador eletrônico
1944 MarkI Aiken Primeiro computador norte~americano de uso geral
1946 ENIAC Eckert/Mauchley A história moderna dos computadores começa aqui
1949 EDSAC Wilkes Primeiro computador com programa armazenado
Whirlwind I MJ.T.
1951 Primeiro computador de tempo real
von Neumann
1952 IAS A maioria das máquinas atuais usa esse projeto
1960 PDP-l DEC Primeiro minicomputador (50 vendidos)
1961 1401 7094 IBM Máquina para pequenos negócios de enorme popularidade
1962 B5000 360 IBM Dominou a computação científica no início da década de
1963 6600 PDP- Burroughs 1960 Primeira máquina projetada para uma linguagem de alto
1964 8 IBM CDC nível Primeira linha de produto projetada como uma família
1964 Primeiro supercomputador centífico
1965 DEC Primeiro mínicomputador de mercado de massa (50 míl vendidos I
1970 PDP-ll DEC Domínou os minicomputadores na década de 1970
1974 8080 Intel Primeiro computador de uso geral de 8 bits em um chip Primeiro
1974 CRAY-l Cray supercomputador vetorial
1978 VAX DEC Primeiro superminícomputador de 32 bits
1981 IBM PC IBM Deu inicio à era moderna do computador pessoal
Osborne
1981 Osborne-l Primeiro computador portátil
Lisa
1983 Apple Primeiro computador pessoal com uma GUI Primeiro
1985 386 Intel ancestral de 32-bits da linha Pentium Primeira
MIPS
1985 MIPS máquina comercial RISC
1987 SPARC SUn Primeira.estação de trabalho RISC.baseada em SPARC
1990 RS6000 IBM Primeira máquina superescalar
1992 Alpha DEC Primeiro computador pessoal de 64 bits
1993
Newton
Apple Primeiro computador palmtop

1.2.1 A geração zero - computadores mecânicos (1642-1945)


A primeira pessoa a construir uma máquina de calcular operacional foi o cientista francês Blaise Pascal
(1623-1662), em honra de quem a linguagem Pascal foi batizada. Esse dispositivo, construído em 1642, quando
Pascal tinha apenas 19 anos, foi projetado para ajudar seu pai, um coletor de impostos do governo francês. Era inteiramente
mecânico, usava engrenagens e funcionava com uma manivela operada à mão.
A máquina de Pascal podia efetuar apenas operações de adição e subtração, mas 30 anos mais tarde o grande
matemático alemão, barão Gottfried Wilhelm von Leibniz (1646-1716), construiu uma outra máquina mecânica que
também podia multiplicar e dividir. Na verdade, Leibniz construiu o equivalente a uma calculadora de bolso de quatro
operações três séculos atrás.
Durante 150 anos nada de muito importante aconteceu, até que um professor de matemática da Universidade de
Cambridge, Charles Babbage (1792-1871), o inventor do velocímetro, projetou e construiu sua primeira máquina
diferencial. Esse dispositivo mecânico que, assim como o de Pascal, só podia somar e subtrair, foi projetado para calcular
tabelas de números úteis para a navegação naval. Toda a construção da máqui
na foi projetada para executar um único algoritmo, o método de diferenças finitas que usava polinômios. A característica mais
interessante da máquina diferencial era seu método de saída: ela perfurava seus resultados sobre uma chapa de gravação de
cobre com uma punção de aço, prenunciando futuros meios de escrita única como cartões perfurados e CD-ROMS.
Embora a máquina diferencial funcionasse razoavelmente bem, Babbage logo se cansou dessa máquina que só podia
executar um único algoritmo. Ele começou a gastar quantidades cada vez maiores de seu tempo e da fortuna da família (sem
mencionar 17 mil libras do governo) no projeto e construção de uma sucessora denominada máquina analítica. A máquina
analítica tinha quatro componentes: a armazenagem (memória), o moinho (unidade de cálculo), a seção de entrada (leitora
de cartões perfurados) e a seção de saída (saída perfurada e impressa). A armazenagem consistia em 1.000 palavras de 50
algarismos decimais, cada uma usada para conter variáveis e resultados. O moinho podia aceitar operandos da
armazenagem e então os somava, subtraía, multiplicava ou dividia e, por fim, devolvia o resultado à armazenagem. Assim
como a máquina diferencial, ela era inteiramente mecânica.
O grande avanço da máquina analítica era ser de uso geral. Lia instruções de cartões perfurados e as executava.
Algumas instruções mandavam a máquina buscar dois números na armazenagem, trazê-los até o moinho, efetuar uma
operação com eles (por exemplo, adição) e enviar o resultado de volta para a armazenagem. Outras instruções podiam testar
um número e desviá-lo condicionalmente, dependendo de ele ser positivo ou negativo.
Perfurando um programa diferente nos cartões de entrada, era possível fazer com que a máquina analítica realizasse
cálculos diversos, o que não acontecia com a máquina diferencial.
Visto que a máquina analítica era programável em uma linguagem de montagem simples, ela precisava de software.
Para produzir esse software, Babbage contratou uma jovem de nome Ada Augusta Lovelace, que era filha do famoso poeta
britânico lorde Byron. Assim, Ada Lovelace foi a primeira programadora de computadores do mundo. A linguagem de
programação Ada@ tem esse nome para homenageá-Ia.
Infelizmente, assim como muitos projetistas modernos, Babbage nunca conseguiu depurar completamente o hardware.
O problema era que ele precisava de milhares e milhares de dentes e rodas e engrenagens produzidos com um grau de
precisão que a tecnologia do século XIX não podia oferecer. Ainda assim, suas idéias estavam muito à frente de sua época e
até hoje a maioria dos computadores modernos tem uma estrutura muito semelhante à da máquina analítica, portanto é mais
do que justo dizer que Babbage foi o avô do computador digital moderno.
O seguinte desenvolvimento importante ocorreu no final da década de 1930, quando um estudante de engenharia
alemão chamado Konrad Zuse construiu uma série de máquinas calculadoras automáticas usando relés eletromagnéticos.
Ele não conseguiu financiamento do governo após o início da guerra porque os burocratas governamentais esperavam
ganhar a guerra tão rapidamente que a nova máquina só estaria pronta após o término do conflito. Zuse não conhecia o
trabalho de Babbage e suas máquinas foram destruídas pelo bombardeio aliado de Berlim em
1944, portanto seu trabalho não teve nenhuma influência sobre as máquinas subseqüentes. Mesmo assim ele foi um dos
pioneiros da área.
Um pouco mais tarde, nos Estados Unidos, duas pessoas também projetaram calculadoras, John Atanasoff no Iowa
State College e George Stibbitz no Bell Labs. A máquina de Atanasoff era surpreendentemente avançada para sua época.
Usava aritmética binária e a memória era composta de capacitores recarregados periodicamente para impedir fuga de carga,
um processo que ele denominou 'sacudir a memória'. Os chips modernos de memória dinâmica (DRAM) funcionam desse
mesmo modo. Infelizmente, a máquina nunca se tomou realmente operacional. De certo modo, Atanasoff era como
Babbage: um visionário que afinal foi derrotado pela tecnologia de hardware inadequada existente em seu tempo.
O computador de Stibbitz, embora mais primitivo do que o de Atanasoff, funcionava de verdade. Stibbitz fez uma
grande demonstração pública de sua máquina durante uma conferência no Dartmouth College em 1940. Uma das pessoas
presentes era John Mauchley, desconhecido professor de física da Universidade da Pennsylvania. Mais tarde o mundo do
computador ouviria mais a respeito do professor Mauchley.
Enquanto Zuse, Stibbitz e Atanasoff estavam projetando calculadoras automáticas, um jovem chamado Howard Aiken
estava remoendo tediosos cálculos numéricos à mão como parte de sua pesquisa de doutorado em Harvard. Depois de
concluído o doutorado, Aiken reconheceu a importância de fazer cálculos à máquina. Foi à biblioteca, descobriu o trabalho
de Babbage e decidiu construir com relés o computador de uso geral que Babbage não tinha conseguido construir com
rodas dentadas.
A primeira máquina de Aiken, a Mark I, foi concluída em Harvard em 1944. Tinha 72 palavras de 23 algarismos
decimais cada e um tempo de instrução de 6 segundos. A entrada e a saída usavam fita de papel perfurada. Quando Aiken
conclui o sucessor dessa máquina, a Mark 11, os computadores de relés já estavam obsoletos. A era eletrônica tinha
começado.
1.2.2 A primeira geração - válvulas (1945-1955)
o estímulo para o computador eletrônico foi a Segunda Guerra Mundial. Durante a fase inicial da guerra, submarinos
alemães estavam causando devastação em navios britânicos. As instruções de comando dos almirantes alemães em Berlim
eram enviadas aos submarinos por rádio, as quais os britânicos podiam interceptar, e interceptavam. O problema era que
essas mensagens eram codificadas usando um dispositivo denominado ENIGMA, cujo antecessor foi projetado pelo
inventor amador e outrora presidente dos Estados Unidos, Thomas Jefferson.
Logo no início da guerra, a inteligência britânica conseguiu adquirir uma máquina ENIGMA da Inteligência Polonesa,
que a tinha roubado dos alemães. Contudo, para decifrar uma mensagem codificada era preciso uma quantidade enorme de
cálculos e, para a mensagem ser de alguma utilidade, era necessário que esse cálculo fosse concluído pouco tempo depois
de ela ter sido interceptada. Para decodificar essas mensagens, o governo britânico montou um laboratório ultra-secreto que
construiu um computador eletrônico denominado COLOSSUS. O famoso matemático britânico Alan Turing ajudou a
projetar essa máquina. O COLOSSUS funcionava desde 1943, mas, uma vez que o governo britânico guardou praticamente
todos os aspectos do projeto como segredo militar durante 30 anos, a linha COLOSSUS foi basicamente um beco sem saída.
Só vale a pena citá-lo por ter sido o primeiro computador digital eletrônico do mundo.
Além de destruir as máquinas de Zuse e estimular a construção do COLOSSUS, a guerra também afetou a
computação nos Estados Unidos. O exército precisava de tabelas de alcance para mirar sua artilharia pesada e produzia
essas tabelas contratando centenas de mulheres para fazer os cálculos necessários com a utilização de calculadoras de mão -
as mulheres eram consideradas mais caprichosas que os homens. Ainda assim o processo era demorado e freqüentemente
surgiam erros.
John Mauchley, que conhecia o trabalho de Atanasoff, bem como o de Stibbitz, sabia que o exército estava
interessado em calculadoras mecânicas. Como muitos cientistas da computação que vieram depois dele, Mauchley montou
uma proposta solicitando ao exército financiamento para a construção de um computador eletrônico. A pro
posta foi aceita em 1943, e Mauchley e seu aluno de pós-graduação, J. Presper Eckert, passaram a construir um computador
eletrônico ao qual deram o nome de ENIAC (Electronic Numerical Integrator And Compute integrador e computador numérico
eletrônico).
O ENIAC consistia em 18 mil válvulas e 1.500 relés, pesava 30 toneladas e consumia 140 quilowatts de energia. Em
termos de arquitetura, a máquina tinha 20 registradores, cada um com capacidade para conter um número decimal de 10
algarismos. Um registrador decimal é uma memória muito pequena que pode conter desde um número até um outro número
máximo de casas decimais, mais ou menos como o odômetro, que registra quanto um carro rodou em seu tempo de vida
útil.
O ENIAC era programado com o ajuste de até 6 mil interruptores multiposição e com a conexão de uma imensa
quantidade de soquetes com uma verdadeira floresta de cabos de jumpers.
A construção da máquina só foi concluída em 1946, quando era muito tarde para ser de alguma utilidade em relação a
seu propósito original. Todavia, uma vez que a guerra tinha acabado, Mauchley e Eckert receberam permissão para
organizar um curso de verão para descrever seu trabalho para seus colegas cientistas. Aquele curso de verão foi o início de
uma explosão de interesse na construção de grandes computadores digitais.
Após aquele curso de verão histórico, outros pesquisadores se dispuseram a construir computadores eletrônicos. O
primeiro a entrar em operação foi o EDSAC (1949), construído na Universidade de Cambridge por Maurice Wilkes. Entre
outros, figuravam o JOHNIAC, da Rand Corporation; o ILLIAC, da Universidade de Illinois; o MANIAC, do Los Alamos
Laboratory; e o WEIZAC, do Weizmann Institute em Israel.
Eckert e Mauchley logo começaram a trabalhar em um sucessor, o EDVAC (Electronic Discrete Variable Automatic
Compute). Contudo, esse projeto ficou fatalmente comprometido quando eles deixaram a Universidade da Pensilvânia para
fundar uma empresa nova, a Eckert-Mauchley Computer Corporation, na Filadélfia. (O Silicon Valley ainda não tinha sido
inventado.) Após uma série de fusões, essa empresa se tomou a moderna Unisys Corporation.
Como um aparte legal, Eckert e Mauchley solicitaram uma patente alegando que eles haviam inventado o computador
digital. Em retrospecto, possuir essa patente não seria nada mau. Após anos de litígio, o tribunal decidiu que a patente de
Eckert-Mauchley era inválida e que John Atanasoff tinha inventado o computador digital, embora nunca o tivesse
patenteado.
Enquanto Eckert e Mauchley trabalhavam no EDVAC, uma das pessoas envolvidas no projeto ENIAC, John von
Neumann, foi para o Institute of Advanced Studies de Princeton para construir sua própria versão do EDVAC, a máquina
IAS. Von Neumann era um gênio, da mesma estirpe de Leonardo Da Vinci. Falava muitos idiomas, era especialista em
ciências físicas e matemática e guardava na memória tudo que já ouvira, vira ou lera. Conseguia citar sem consulta, palavra
por palavra, o texto de livros que tinha lido havia anos. Na época em que se interessou por computadores, ele já era o mais
eminente matemático do mundo.
Uma das coisas que logo ficou óbvia para ele foi que programar computadores com quantidades imensas de
interruptores e cabos era uma tarefa lenta, tediosa e mecânica. Ele percebeu que o programa podia ser representado em
forma digital na memória do computador, junto com os dados. Também viu que a desajeitada aritmética decimal serial
usada pelo ENIAC, com cada dígito representado por 10 válvulas (1 acesa e 9 apagadas), podia ser substituída usando
aritmética binária paralela, algo que Atanasoff tinha percebido anos antes.
O projeto básico, o primeiro que ele descreveu, agora é conhecido como máquina de Von Neumann. Ela foi usada no
EDSAC, o primeiro computador de programa armazenado, e agora, mais de meio século depois, ainda é