Capítulo TRÊS Componentes do computador e modelo de von Neumann 3 . 1 Breve histórico Uma das mais importantes investidas na área computacional, e que merece registro histórico, foi a do inglês Charles Babbage. Ele projetou dois computadores: Difference Engine (denominado a seguir “Dispositivo Diferencial”), iniciado em 1823, e o Analytical Engine (“Dispositivo Analítico”), concebido em 1834, tendo ambos representado grandes avanços científicos em sua época, embora nenhuma deles tenha sido concluído. O objetivo do Dispositivo Diferencial era o cômputo automático de tabelas matemáticas. Sua única operação era a adição, mas a máquina podia resolver grande número de funções úteis pela técnica de diferenças finitas. Esta máquina foi projetada para polinômios de grau 6 e números binários de 20 dígitos, mas não foi concluída devido a problemas de inadequação da tecnologia mecânica disponível. Outra tentativa de Babbage, foi a construção do Dispositivo Analítico, que deveria realizar qualquer operação matemática automaticamente. Esta máquina já tinha módulos de armazenamento (memória) e uma unidade operadora (realizando 4 operações aritméticas). A entrada e saída de dados era feita através de cartões perfurados. Esta máquina permitia a alteração da seqüência dos comandos executados, dependendo do resultado de testes realizados. Novamente por problemas técnicos, a construção desta máquina não chegou ao final. Na tabela a seguir estão reunidas algumas das principais tentativas de valor histórico no âmbito computacional. Data 1642 Inventor:máquina Pascal 1671 Leibnitz 1827 Babbage: Difference Engine Babbage: Analytical Engine Zuse: Z3 1834 1941 1944 Aiken: Harward Mark I Capacidade adição, subtração Inovações técnicas transferência automática de vai-um; representação em complemento adição, subtração, mecanismo para multiplicação multipl., divisão e divisão avaliação polinomial operação automática por diferenças finitas com diversos passos computador de mecanismo automático de controle propósitos gerais de sequência (programa) computador de primeiros computadores de propósitos gerais propósitos gerais operacionais computador de primeiros computadores de propósitos gerais propósitos gerais operacionais Tabela 3.1 - Principais avanços na computação Uma das primeiras tentativas para construção de computadores eletrônicos foi feita por volta de 1930 por John Atanasoff, na Universidade Estadual de Iowa. Era uma máquina construída com base em válvulas para resolução de equações lineares. O primeiro computador eletrônico de propósitos gerais foi provavelmente o ENIAC (Eletronic Numerical Integrator and Calculator), construído entre 1943 e 1946, na Universidade da Pensilvânia, sob a coordenação de J. Mauchly e J. P. Eckert. Analogamente à primeira máquina de Babbage, parte da motivação do ENIAC foi a necessidade de construir tabelas de forma automática, por interesse do sistema militar americano (tabelas balísticas). Fisicamente, era uma máquina enorme que pesava 30 toneladas e empregava cerca de 18000 3-1 válvulas. Para se ter uma idéia do tempo de execução nesta máquina, eram necessários cerca de 3 ms para realização de uma multiplicação de 10 dígitos (decimais), o que se constituiu em grande avanço para a época. Ele trabalhava preponderantemente com valores decimais e não binários. Na Figura 3.1 é mostrada a estrutura básica do ENIAC. Com o avanço da pesquisa e o conseqüente desenvolvimento tecnológico, houve grandes modificações nos computadores. Basicamente, ao longo do tempo, a tecnologia e os estilos usados na construção de computadores apresentam pontos comuns, que nos permitem classificá-los em gerações. Na tabela a seguir, são apresentadas as gerações de computadores de acordo com sua classificação histórica. Geração Tecnologias Válvulas, 1a memória de tubos (1946 catódicos 54) Transistores, núcleos 2a de ferrite, discos (1955 magnéticos 64) a Circuitos integrados 3 (SSI e MSI) (1965 74) 4a (1975 ?) Característica de hardware aritmética de ponto fixo ponto flutuante registrador índice processadores E/S microprogramação pipeline memória cache Característica de software linguagem de máquina, linguagem assembler ling. alto-nível bibliot. de subrotinas monitores batch multiprogramação multiprocessamento sistema operacional memória virtual Circuitos LSI memórias semicondutoras Exemplo IAS, UNIVAC IBM7094 CDC1604 IBM S/360; DEC PDP-8 Amdahl 470; Intel 8748 Tabela 3.2 - Gerações de computadores Atualmente, esta tabela [HAY78] já poderia ser completada com uma quinta geração que incluiria as máquinas maciçamente paralelas, os circuitos VLSI, as máquinas “data-flow”, etc, dependendo do parâmetro escolhido para embasar esta evolução. leitora de cartões divisor multiplicador impressora e perf. de cartões tabelas de e raiz quadrada funções unidade mestre de programação Figura 3.1 - Estrutura básica do ENIAC 3-2 a c u m u l. 3 . 2 Princípios básicos Cada computador tem um conjunto de operações e convenções único para determinar as posições dos dados com os quais a operação será realizada. Os vários computadores diferem nas operações específicas que fornecem e nos métodos que eles usam para referenciar dados que serão manipulados por uma operação. Em geral, uma operação tem a forma OPERAÇÃO OPERANDOS e é denominada de instrução. OPERAÇÃO especifica a função que será desempenhada. OPERANDOS fornece a maneira de calcular a posição atual dos dados com os quais a operação será realizada. Um programa é constituído de uma seqüência pré-determinada de instruções, que deve ser seguida para que seja atingido o objetivo computacional. Este programa e os dados correspondentes estão armazenados na memória da máquina; o conjunto de instruções (ou programa) deve ser interpretado para realização do processamento, isto é, a informação codificada correspondente às ações e operandos deve ser entendida e então processada. A memória de um sistema de computador tem a função de armazenar dados e instruções; é organizada em posições, que podem ser visualizadas como elementos em uma matriz. Cada elemento tem um endereço. Assim, pode-se falar de uma memória que tenha x posições: cada posição pode ser referenciada diretamente de acordo com a sua colocação na seqüência. Por exemplo, se uma memória tem 4096 posições, existem posições de memória 0, 1, 2, 3,...., 4094 e 4095. Quando um destes números aparece nos circuitos de controle conectados à memória, o conteúdo (o valor que está na posição) será trazido da memória para os circuitos da unidade de processamento ou a informação na unidade de processamento será armazenada na memória, dependendo do trabalho associado com o endereço. Instruções em um computador são executadas em uma seqüência determinada por suas posições de memória. Na maioria dos computadores (que formam a classe das chamadas máquinas de von Neumann, cujo modelo básico será visto na seção 3.5), instruções e dados são distribuídos em posições de memória. O endereço representa uma posição particular na memória e pode ser formado de várias maneiras. A representação trivial de um endereço está na parte de uma instrução chamada campo de endereço. Contudo, há várias maneiras de se modificar um campo de endereço por valores em outras partes do processador (aritmética de endereços). As diversas possibilidades e vantagens destas técnicas serão mostradas mais adiante na disciplina. A unidade lógica e aritmética realiza ações indicadas nas instruções, executando operações numéricas (aritméticas) e não numéricas (lógicas) além da preparação de informações para desvios do programa. O controle do programa e a unidade lógica e aritmética formam a unidade central de processamento (UCP), ou simplesmente processador. Busca - decodificação - execução de instruções Um elemento no processador, denominado de contador de instruções ou apontador de instruções, contém a posição da próxima instrução a ser executada. Quando uma seqüência de execução de instruções tem início, a instrução cujo endereço está no contador de instruções é trazida da memória para uma área de armazenamento chamada registrador de instrução. Este processo consiste na busca de instrução. A instrução é interpretada por circuitos de decodificação que fazem com que sinais eletrônicos sejam gerados no processador como resultado do valor do campo de operação, isto é, decodificam a informação correspondente à operação a ser realizada. Esses sinais, ou seqüência de sinais, resultam na execução da instrução. Execução é a aplicação da função do operador nos operandos. Quando a execução de uma instrução é 3-3 terminada, o contador de instruções é atualizado para o endereço de memória da próxima instrução. Esta instrução é então trazida da memória para o registrador de instruções e executada, repetindo-se assim o ciclo de busca-decodificação-execução. A seqüência de instruções pode mudar como resultado de uma instrução que direciona um desvio (também chamada transferência ou salto). Estas instruções contêm o endereço da próxima instrução a ser executada ao invés do endereço de um operando. Elas causam mudanças no fluxo do programa como resultados das condições nos dados. O desvio condicional representado por uma estrutura de programação de alto nível de IF (teste para uma condição especificada e alteração do fluxo de programa se a condição é atendida) traduzse em algum tipo de instrução de desvio. 3 . 3 Elementos funcionais básicos Um computador é composto por blocos convencionalmente chamados de memória, unidades operacionais, unidades de controle e dispositivos de entrada e saída (Figura 3.2). A unidade operacional e a unidade de controle tem funcionalidade específica, conforme será visto na seqüência. Reunidas, entretanto, recebem no seu conjunto a denominação de unidade central de processamento (UCP) ou processador. Memórias, unidades operacionais, unidades de controle e dispositivos de entrada e saída são formados por elementos de menor complexidade, tais como registradores, contadores, multiplexadores, seletores, decodificadores, somadores e portas lógicas (AND, OR, INVERSOR). Registradores são elementos digitais com capacidade de armazenar dados. Têm associados a si sinais de carga, que determinam quando serão armazenados novos conteúdos nestes elementos; ao ser acionado este sinal (carga), o registrador copia para si o dado que está em suas linhas de entrada. Contadores, multiplexadores, seletores, decodificadores, somadores e portas lógicas são elementos com capacidade de operar sobre dados, alterando-os ou fornecendo um novo dado como resultado da operação que realizam. Elementos digitais necessitam ser ativados ou habilitados para realizar uma determinada operação. Os sinais responsáveis pela ativação ou habilitação de componentes digitais são conhecidos como sinais de controle. memória controle unidade operacional entrada/ saída Figura 3.2 - Elementos básicos de um computador Dados são transferidos, entre os diversos elementos de um computador, por caminhos físicos chamados barramentos. Barramentos são caminhos físicos que permitem o transporte de dados entre os vários elementos da parte operacional, memória e sistema de 3-4 entrada e saída. Um barramento só pode receber dados de uma fonte de cada vez. Do ponto de vista de arquitetura, um barramento se caracteriza pela sua largura em bits. A largura em bits do barramento deve corresponder ao comprimento dos elementos (dados, endereço, controle) que são por ele transportados. Cada um dos blocos básicos do computador é comentado, em detalhes, a seguir. 3 . 3 . 1 Memória A memória é formada por elementos armazenadores de informação. Uma memória está dividida em palavras. Cada palavra ocupa uma posição de memória e é identificada univocamente por um endereço. O conteúdo armazenado nas palavras da memória tanto pode representar dados como instruções. Um esquema da estrutura convencional para a memória de um computador é mostrado na Figura 3.3. RDM in R E M read memória write RDM out Figura 3.3 - Modelo estrutural da memória Os registradores mostrados na Figura 3.3 são: REM : registrador de endereços da memória - contém o endereço do dado a ser lido ou escrito na memória. RDM i n : registrador de dados da memória (entrada) - contém o dado a ser escrito na memória. RDM out : registrador de dados da memória (saída) - contém o dado lido da memória. Os sinais de controle significam: read: leitura da memória - o conteúdo da posição de memória endereçada por REM é copiada em RDMout . write: escrita na memória - a posição de memória endereçada por REM recebe o conteúdo de RDMin . Uma memória é caracterizada por vários parâmetros. Os mais importantes são: tamanho, velocidade e tecnologia. No nível de arquitetura, interessam: tamanho da palavra em bits e tamanho da memória em palavras. Estes tamanhos geralmente são indicados sob a forma de potências de dois. O tamanho da palavra determina o comprimento em bits do RDM (registrador de dados) e o tamanho da memória o comprimento em bits do REM (registrador de endereços). 3-5 3 . 3 . 2 Unidade operacional A unidade operacional, também chamada de bloco operacional, executa as transformações sobre dados especificadas pelas instruções de um computador. Compõe-se basicamente de uma unidade lógica e aritmética, de registradores de uso geral e específico e dos barramentos que interligam todos esses elementos. O número, tamanho e uso dos registradores e a quantidade e tipo de operações que a unidade lógica e aritmética realiza são alguns dos fatores que determinam o porte de um processador. Unidade lógica e aritmética ( ULA ) A ULA realiza operações aritméticas e operações lógicas sobre um ou mais operandos. Exemplos de operações realizadas pela ULA: soma de dois operandos; negação de um operando; inversão de um operando; AND (“E” lógico) de dois operandos; OR (“OU” lógico) de dois operandos; deslocamento de um operando para a esquerda ou direita ; rotação de um operando para a esquerda ou direita As operações da ULA são, geralmente, muito simples. Funções mais complexas, exigidas pelas instruções da máquina, são realizadas pela ativação seqüencial das várias operações básicas disponíveis. Um exemplo é a execução de instruções de multiplicação em alguns computadores, que compreende a ativação de operações sucessivas de soma e deslocamento na ULA. A ULA fornece o resultado da operação e também algumas indicações sobre a operação realizada. Tais indicações são chamadas códigos de condição. Exemplos de alguns códigos de condição comumente gerados na ULA são: • Overflow: (ou estouro de campo) indica que o resultado de uma operação aritmética não pode ser representado no espaço (tamanho da palavra) disponível. • Sinal: indica se o resultado da operação é negativo ou positivo. • Carry: dependendo da operação realizada (soma ou subtração) pode representar o bit de vai-um (carry-out) ou vem-um (borrow-out). Usado muitas vezes também em operações de deslocamento para guardar ou fornecer o bit deslocado. A indicação de carry não deve ser confundida com overflow. • Zero: indica se o resultado da operação realizada é nulo. O modelo estrutural da unidade lógica e aritmética é mostrado na Figura 3.4. operandos controle U L A códigos de condição resultado Figura 3.4 - Modelo estrutural da ULA 3-6 Os sinais de controle que devem ser fornecidos para a ULA servem para selecionar a operação desejada entre as operações básicas disponíveis. Convém salientar que a ULA não armazena nem o resultado, nem os operandos, nem os códigos de condição gerados. Uma ULA se caracteriza por: • comprimento em bits dos operandos • número e tipo de operações • códigos de condição gerados Acumulador O acumulador é um registrador e tem por função armazenar um operando e/ou um resultado fornecido pela ULA. Nos computadores mais simples é encontrado apenas um acumulador. Em algumas arquiteturas mais complexas vários registradores podem desempenhar as funções de um acumulador. Como todos os registradores, o acumulador é ativado por um sinal de controle de carga. A cada sinal de carga, o dado na entrada do registrador é copiado para o seu interior (obviamente o antigo conteúdo do acumulador é perdido). Um acumulador, sendo um registrador, se caracteriza ao nível de arquitetura apenas pelo seu comprimento em bits. 3 . 3 . 3 Unidade de controle Para gerenciar o fluxo interno de dados e o instante preciso em que ocorrem as transferências entre uma unidade e outra são necessários sinais de controle. Esses sinais são fornecidos por um elemento conhecido por unidade de controle. Cada sinal de controle comanda uma microoperação. Uma microoperação pode ser responsável pela realização de uma carga em um registrador, uma seleção de um dado para entrada em um determinado componente, uma ativação da memória, a seleção de uma operação da ULA ou a habilitação de um circuito lógico, para citar alguns exemplos. Unidades de controle são máquinas de estado finitas (FSM) realizadas por lógica seqüencial. Lógica seqüencial e lógica combinacional são caracterizadas, informalmente, como segue: • Lógica seqüencial: os sinais de saída são função dos sinais de entrada e do estado anterior do sistema. • Lógica combinacional: os sinais de saída são função exclusiva dos sinais de entrada. Existem várias formas de implementar lógica seqüencial. Tais formas de implementação caracterizam a organização da unidade de controle. As duas organizações usuais são: • Organização convencional: a unidade de controle é composta por componentes digitais como flip-flops, contadores e decodificadores, que geram, seqüencialmente e nos instantes de tempo adequados, todos os sinais de controle necessários à ativação da unidade operacional, do sistema de entrada e saída e da memória. • Organização microprogramada: em uma unidade de controle microprogramada, os sinais de controle estão armazenados numa memória especial chamada memória de controle. Vários sinais de controle são buscados a cada acesso à memória de controle. Esses sinais estão agrupados em longas palavras chamadas microinstruções. Um conjunto de microinstruções forma um microprograma. 3-7 A unidade de controle, baseada em sinais de entrada obtidos do registrador de estado (RST) e do registrador de instruções (RI), gera como saída todos os sinais de controle necessários para a unidade operacional (Figura 3.5). O registrador de instruções é um elemento do bloco de controle, o registrador de estado é um elemento da interface entre a unidade de controle e a unidade operacional. Em função de uma arquitetura específica, esse último registrador tanto pode aparecer classificado numa unidade como em outra. RI RST unidade de controle sinais de controle Figura 3.5 - Esquema de uma unidade de controle 3 . 3 . 4 Registradores especiais Existem, no computador, alguns registradores com funções especiais, conforme será explicado a seguir. Dependendo da arquitetura e da organização de cada máquina, alguns registradores podem estar posicionados na unidade de controle ou na unidade operacional. Esta localização, entretanto, no momento não é relevante; aqui será assumida a posição adotada por cada máquina estudada. Apontador de instruções O apontador de instruções é um registrador e tem por função manter atualizado o endereço de memória da próxima instrução que deve ser executada. Também é chamado de contador do programa (ou PC, do inglês Program Counter). O nome contador do programa se deve ao fato de, no modelo básico de um computador, instruções consecutivas de um programa serem armazenadas em palavras da memória que possuem endereços também consecutivos. Assim, para acessar a próxima instrução, basta contar mais um. Do ponto de vista de arquitetura, um apontador de instruções se caracteriza pelo seu comprimento em bits. Como o PC contém um endereço de memória, o comprimento do PC é função do tamanho da memória onde estão armazenados os programas em execução. Registrador de instruções ( RI ) O registrador de instruções armazena a instrução que está sendo executada. Em função do conteúdo desse registrador, a unidade de controle determina quais os sinais de controle devem ser gerados para executar as operações determinadas pela instrução. Do ponto de vista de arquitetura, um registrador de instruções se caracteriza pelo seu comprimento em bits. O comprimento do RI depende do tamanho e codificação das instruções do computador. Registrador de estado ( RST ) O registrador de estado armazena códigos de condição gerados pela unidade lógica e aritmética (e, eventualmente, por outros elementos, como os sinais de interrupção gerados por dispositivos de entrada e saída). Em função do conteúdo desse registrador, a unidade de controle toma decisões sobre a geração ou não de certos sinais de controle. Do ponto de vista 3-8 de arquitetura, um registrador de estado se caracteriza pelo seu comprimento em bits, que é uma função do número de códigos de condição implementados na máquina. 3 . 3 . 5 Conjunto de instruções e modos de endereçamento Uma instrução é um conjunto de bits devidamente codificados que indica ao computador que seqüência de microoperações ele deve realizar. Instruções são classificadas por semelhança de propósito e formato. Classificações comuns incluem, entre outras: • instruções de transferência de dados • instruções aritméticas e lógicas • instruções de teste e desvio O conjunto de todas as instruções que um determinado computador reconhece e pode executar é chamado de conjunto de instruções. Qualquer seqüência finita de instruções de um determinado conjunto de instruções compõe um programa. Muitas da instruções de um computador realizam operações sobre operandos (p.ex. soma de dois elementos). Operandos podem estar em qualquer posição da memória ou em qualquer registrador (inclusive em um registrador pertencente a um dispositivo de entrada e saída). Para que a unidade de controle saiba onde achar um operando é necessário que o endereço do operando apareça junto a instrução. Nas instruções de desvio (parecidas com GOTO e IF-THEN em linguagens de alto nível) é necessário indicar, ao invés de endereço de operando, para qual posição ou endereço de programa se quer desviar. As diversas formas em que o endereço de um operando pode aparecer, somadas às diversas formas em que um endereço de desvio pode ser encontrado em um computador, caracterizam os modos de endereçamento desse computador. 3 . 3 . 6 Ciclo de busca-decodificação-execução de instruções Busca, decodificação e execução de instruções são as tarefas básicas realizadas por um processador. Caracterizam um ciclo, pois as tarefas são executadas repetidamente, sempre e sempre, até que seja decodificada uma instrução que indique parada ao computador (halt, stop, wait, etc). Busca: na fase de busca é lida uma instrução da memória. Essa fase envolve: • copiar o apontador de programa (PC ) para o registrador de endereços da memória (REM), • ler uma instrução da memória, • copiar o registrador de dados da memória (RDM) para o registrador de instruções (RI), • atualizar o apontador de programa (PC ). Decodificação: nessa fase é determinada qual instrução deve ser executada. A decodificação geralmente é realizada por lógica combinacional. Execução: na fase de execução, para cada tipo de instrução é realizado, conforme necessário: • cálculo do endereço de operandos, • busca de operandos da memória, • seleção de operação da ULA, • carga de registradores, • escrita de operandos na memória, • atualização do PC para desvios. 3-9 O controle de todas as operações do ciclo de busca-decodificação-execução de instruções é de responsabilidade da unidade de controle. O programador, mesmo o de baixo nível (ou seja, aquele que conhece a linguagem de máquina de seu computador), não precisa se preocupar com isso, a não ser para calcular os tempos envolvidos na execução de seu programa. 3 . 3 . 7 Programação de um processador A única linguagem que um processador entende e tem condições de executar não é, ao contrário do que muitos pensam, o inglês, mas sim linguagem de máquina. Linguagem de máquina é uma imagem numérica (binária) que representa a codificação do conjunto de instruções de um computador. Todos os programas objeto de um computador estão representados e armazenados em linguagem de máquina. Representações numéricas são de difícil manipulação até mesmo por programadores experientes. Programas em linguagem de máquina são difíceis de elaborar, testar e alterar. Para facilitar as tarefas de programação e depuração, mnemônicos (em inglês) foram associados aos códigos das instruções, nomes aos operandos e rótulos (labels) às posições ocupadas pelo programa. A partir de então, não é mais necessário trabalhar com códigos numéricos, pois toda a programação de baixo nível é feita usando símbolos. Um programa escrito com auxílio de símbolos, ou seja em linguagem simbólica, precisa ser traduzido em linguagem de máquina para que possa ser executado. Essa tradução recebe o nome de montagem e, quando automatizada, o programa que a realiza recebe o nome de montador. Um montador realiza praticamente apenas uma tradução “um para um” das instruções da linguagem simbólica para instruções de máquina (ao contrário de um compilador, que gera rotinas em linguagem de máquina para cada instrução da linguagem de alto nível e depois otimiza código e alocação de variáveis). Montadores modernos, para computadores de 16 e 32 bits por exemplo, são bastante poderosos e confortáveis, aceitando comandos específicos (chamados comumente de pseudo-instruções) e tipos de dados não disponíveis na linguagem de máquina. 3 . 4 Um computador de primeira geração: o EDVAC No ENIAC, e nas máquinas que o antecederam, os programas e os dados eram armazenados em memórias separadas. O armazenamento inicial de programas e sua alteração constituía-se em uma atividade extremamente cansativa. A idéia de armazenar programas e dados na mesma unidade de memória - que corresponde ao conceito de programa armazenado - é atribuída ao matemático húngaro John von Neumann (1903 – 1957), que atuou como consultor no projeto do ENIAC. Sua proposta foi publicada em 1945 para um computador novo, o EDVAC (Electronic Discrete Variable Computer). Além de facilitar o processo de programação, o conceito de programa armazenado torna possível ao programa modificar suas próprias instruções. Além de ser um computador de programa armazenado, o EDVAC trazia outras inovações: memória de capacidade bastante aumentada (principal 1 com 1024 palavras, implementada através de uma linha de atraso em mercúrio, e secundária magnética de 20k palavras); representação interna em binário; e circuitos aritméticos binários seriais, devido à entrada de dados serial. A estrutura básica de um computador de primeira geração, que pode ser correspondente a uma máquina semelhante ao EDVAC, é mostrada na Figura 3.6. 1 A memória principal deve ser rápida: armazena pelo menos o programa em execução e os dados correspondentes. A memória secundária é mais lenta e serve para armazenar grandes volumes de dados e programas que não estão em execução. 3-10 unidades de memória secundárias unidade central de processamento memória principal unidade lógicoaritmética teletipo unidade de controle de programa leitora de cartões impressora e perfuradora de cartões equipamentos de E/S Figura 3.6 - Arquitetura de um computador de primeira geração Antes da execução de um programa no EDVAC, todas as instruções e dados eram colocados na memória principal. Uma instrução aritmética, por exemplo, tinha o seguinte formato: A1 A2 A3 A4 OP que significava o seguinte: realize a operação OP com o conteúdo das posições de memória principal, cujos endereços são A1 e A 2 e coloque o resultado na posição A3. O quarto endereço, A4, especifica a posição da próxima instrução a ser executada. Uma instrução condicional tinha o seguinte formato: A1 A2 A3 A4 C que significava o seguinte: se o número em A1 não é menor do que o número em A2 então execute a instrução constante na posição A3, senão, execute a instrução em A4. Ainda existia um par de instruções de entrada e saída para a transferência de informações entre as memórias principal e secundária. Nestas instruções, o campo do segundo endereço era dividido em dois componentes, um modificador de operação m, que indicava a direção da transferência de dados, e um número n, que representava o endereço do condutor no meio de armazenamento secundário a ser usado. O formato da instrução era: A1 m,n A3 A4 W significando: 1. Se m = 1, transfira para o condutor n a seqüência de palavras armazenadas na memória principal nas posições A1, A1+1, A 1+2, ....., A 3. 2. Se m = 2, transfira do condutor n a seqüência de palavras para as posições A1, A 1+1, A1+2, ....., A 3 na memória principal. Novamente A4 era o endereço da próxima instrução a ser realizada. Observe na estrutura do EDVAC, mostrada na Figura 3.6, que há dois conjuntos de linhas originados na unidade central de processamento que conduzem informações entre esta unidade e os equipamentos de entrada e saída. O conjunto de linhas que parte do bloco 3-11 denominado, na figura, de unidade de controle de programa conduz informações de controle aos elementos de E/S, determinando quais atividades devem ser realizadas nestes elementos (por exemplo, indicando à leitora de cartões que ela deve efetuar a leitura do próximo cartão, ou indicando à impressora que ela deve imprimir o caracter que se encontra disponível). O outro conjunto de linhas, que está relacionado ao bloco unidade lógicoaritmética conduz dados que serão ou que foram processados. Assim, este conjunto de linhas transporta dados provenientes da leitora de cartões, transporta dados para a teletipo e recebidos da mesma, e assim por diante. O equipamento de entrada e saída do EDVAC consistia de um dispositivo semelhante a uma máquina de escrever, que transferia informação diretamente para os condutores magnéticos, e uma impressora, que revertia este processo. O EDVAC tornou-se operacional em 1951. Principais inconvenientes do EDVAC O formato de instrução utilizado no EDVAC, bem como a arquitetura e organização escolhidas para a sua implementação, resultam em problemas, tais como os explicados a seguir. Considere o formato de uma instrução aritmética, por exemplo, de uma soma: tem-se quatro operandos mais o código de operação. Todos os operandos correspondem a endereços de memória; dois são endereços das parcelas, um é o endereço para o armazenamento do resultado final, e outro é o endereço da próxima instrução. Isto implica em um grande número de interações com a memória, que não podem ser feitas paralelamente (considerando a estrutura proposta). Como o tempo de acesso para leitura e escrita de informações para a memória é grande, se comparado ao tempo empregado para processamento interno à UCP, este constitui-se em um entrave significativo aos índices de desempenho do computador. Este entrave é referido como “gargalo de von Neumann”. Como formas de resolver ou diminuir o problema, pode-se pensar em soluções tais como diminuir o número de operandos, fazendo com que alguns deles sejam implícitos. Por exemplo: • se o resultado de uma operação de soma for armazenado na posição onde inicialmente está um dos operandos, não é necessário especificar o endereço do resultado (obviamente neste caso o valor inicial do operando será perdido); • se o resultado de uma operação de soma for armazenado em uma posição previamente convencionada, como no endereço seguinte ao de um dos operandos, para citar um exemplo, ou em uma posição especial de memória destinada só para este fim, não é necessário especificar o endereço do resultado; • se o endereço da próxima instrução for previamente convencionado, não há necessidade de incluí-lo na instrução. Esta especificação explícita de endereços traz outro inconveniente. No caso do EDVAC, a memória principal tem 1024 palavras: são necessários 10 bits para endereçá-la. Portanto, uma instrução aritmética necessitará mais de 40 bits para sua representação (4 x 10 de endereçamento mais x bits para definição da operação a ser executada) exigindo palavras de memória grandes ou esquemas especiais de organização de informações. Estes problemas começaram a ser resolvidos pelo próprio von Neumann na máquina seguinte, que ficou conhecida pela sigla IAS. 3 . 5 Modelo de von Neumann: o computador IAS Em 1946, Von Neumann e sua equipe iniciaram o projeto de um novo computador de programa armazenado: o computador IAS, elaborado no Instituto de Estudos Avançados de Princeton (Princeton Institute for Advanced Studies). Esta máquina usava como memória principal um tubo de raios catódicos de acesso randômico, o que permitia o acesso a uma 3-12 palavra inteira em uma única operação. Cada instrução continha somente um endereço de memória e tinha o seguinte formato: OP A Esta máquina foi largamente divulgada, influenciando sobremaneira o projeto subsequente de outras máquinas. Os blocos básicos componentes do IAS são: • uma unidade de processamento central, para execução de operações aritméticas e lógicas; • uma unidade de controle de programa, para determinar o sequenciamento das instruções a serem executadas e gerar os sinais de controle para as outras unidades. Estes sinais determinam as ações a serem executadas; • uma unidade de memória principal, com capacidade de 4096 palavras; • uma unidade de entrada e saída. As ligações entre estas unidades são mostradas na Figura 3.7. Unidade Central de Processamento unidade lógica e aritmética AC MQ circuitos lógico-aritméticos equipamento de entrada e saída DR instruções e dados IBR PC memória principal IR AR circuitos de controle : sinais de : controle endereços Unidade de controle de programa Figura 3.7 - Estrutura do IAS Na unidade central de processamento do IAS existe um novo elemento de armazenamento de dados, que é o acumulador (AC). Este elemento atua como uma memória rápida que guarda 3-13 de forma imediata o resultado das operações realizadas na unidade lógico-aritmética. O acumulador é empregado intensamente em instruções que realizam estas operações. Suponha-se a realização de um programa que executa a soma de dois números. Os dois números a serem somados estão armazenados nas posições 100 e 101 de memória. O resultado deve ser guardado na posição 102. Na descrição abaixo, a seta (←) indica a transferência de informação; assim, A ← B significa que A recebe o conteúdo de B Instrução AC ← M(100) AC ← AC + M(101) M(102) ← AC Comentários Transfere conteúdo da memória, end. 100, para acumulador Soma conteúdo da posição 101 ao conteúdo do acumulador e coloca o resultado no acumulador Armazena o conteúdo do acumulador no endereço 102 Figura 3.8 - Exemplo de programa no IAS Na Figura 3.7 é mostrada a estrutura do computador IAS, cuja arquitetura básica ficou conhecida como modelo de von Neumann. A terminologia não corresponde exatamente a utilizada originalmente; os termos estão atualizados para o seu equivalente próximo na nomenclatura atual. Organização da memória A memória do IAS tinha 212 = 4096 palavras, sendo as palavras compostas por 40 bits. Estes 40 bits, eram a quantidade de informações que podiam ser transferidas, em cada momento, da UCP para a memória (em um passo). Estas palavras armazenadas na memória podiam corresponder a instruções ou a dados. Formato dos dados Os dados eram números binários representados em ponto fixo e codificados em complemento de dois. Sendo assim, o bit mais a esquerda do número correspondia ao sinal do mesmo e as operações de soma e subtração eram ambas executadas por um somador. O ponto do número estava supostamente entre os bits 0 e 1, permitindo assim a representação direta apenas de números situados no intervalo entre 0 e 1; os demais números deveriam ser previamente ajustados antes da realização de cálculos. O formato de um dado é representado a seguir. 0 1 39 ↑ Bit de sinal Figura 3.9 - Formato dos dados do IAS Formato das instruções: cada instrução podia ser representada com 20 bits; portanto, uma palavra de memória podia acomodar 2 instruções. Oito bits, os mais da esquerda ou “mais significativos” eram usados para o código da operação a ser realizada, e os outros doze bits eram usados para especificar o endereço de uma posição de memória, conforme mostrado abaixo. Instrução posicionada à esquerda 0 8 cód.operação endereço Instrução posicionada à direita 19 20 28 cód.operação Figura 3.10 - Formato das instruções do IAS 3-14 39 endereço Comparando-se esta instrução com o formato de instrução anteriormente apresentado para o EDVAC, na qual eram expressos 4 endereços, pode-se observar que ocorreu uma redução substancial no comprimento da palavra de instrução. As alterações na organização do IAS, que tornaram possível esta redução são as seguintes: • há registradores pré-definidos na UCP para armazenarem operandos e resultados, isto é, os endereços dos registradores da UCP estão implícitos no código de operação. Assim, as instruções do IAS utilizam estes registradores automaticamente. • as instruções de um programa estão armazenadas na memória principal de maneira quase inteiramente seqüencial (excetuando os casos de desvio apenas), considerado o seguimento que deve ser usado na execução; portanto, o endereço da próxima instrução é o endereço atual mais 1. Isto elimina a necessidade do campo onde constava o endereço da próxima instrução. As situações em que devem ocorrer desvios são resolvidas por instruções especiais. 3 . 5 . 1 Organização da UCP A UCP do IAS contém alguns registradores para armazenamento temporário de instruções, endereços de memória e dados. O processamento de dados é realizado pelos circuitos lógicoaritméticos. Os circuitos de controle decodificam instruções, direcionam a informação através do sistema, e fornecem a temporização dos sinais para todas as ações. Existe um relógio para a sincronização da operação do sistema. Basicamente, existem as seguintes estruturas, cujas funções são descritas resumidamente: • memória principal M: para o armazenamento de programas e dados; • registrador de dados DR (com 40 bits): recebe dados lidos da posição X da memória (DR ← M(X)) ou fornece dados que serão gravados na posição X da memória (M(X) ← DR). Também pode ser usado para armazenar dados temporariamente, durante a execução de uma instrução; • registrador de endereços AR (com 12 bits): armazena o endereço que servirá para apontar posições da memória; • acumulador AC: armazenamento temporário de operandos; • registrador multiplicador-quociente MQ: armazenamento temporário de operandos; • registrador IBR: como no IAS são lidas simultaneamente duas instruções da memória, a que não é executada imediatamente é armazenada no IBR; a que será executada em seguida, o código de operação é armazenado no registrador de instruções IR, onde é decodificado. O campo de endereço desta instrução é transferido para AR; • contador de programa PC ou registrador de endereço da instrução: armazena o endereço da próxima instrução a ser executada. 3 . 5 . 2 Conjunto de instruções As instruções do IAS estão listadas na Tabela 3.3 a seguir. Elas estão divididas em agrupamentos de acordo com a sua função: instruções de transferência, de desvio condicional e incondicional, aritméticas e de modificação de endereço. Para a descrição é usada uma linguagem de transferência a nível de registradores, que descreve brevemente as instruções e microoperações que ocorrem a nível interno no computador. As posições de armazenamento são descritas por siglas (como, AR, M), a transferência de informações é descrita por uma seta, e os elementos de armazenamento 3-15 “matriciais”, como a memória, são especificados por índices entre parênteses. Portanto, na memória de 4096 x 40, como é o caso do IAS, M(X,0:19) indica os bits de 0 a 19 da palavra na posição ou endereço X da memória. Conjunto de instruções do computador IAS Tipo instrução Notação Transferência de AC ← MQ dados MQ ← M(X) AC ← M(X) Descrição Transfere conteúdo do reg. MQ para o acumulador AC Transfere conteúdo da posição X de memória para MQ Transfere conteúdo de AC para a posição de memória X Transfere M(X) para AC AC ← – M(X) Transfere – M(X) para AC AC ← |M(X)| Transfere valor absoluto de M(X) para AC M(X) ← AC Desvio incondicional Desvio condicional Aritmética AC ← – |M(X)| go to M(X, 0:19) Transfere – |M(X)| para AC busque a próxima instrução da metade esquerda de M(X) go to M(X, 20:39) busque a próxima instrução da metade direita de M(X) se AC ≥ 0 então desvie se o número em AC não for negativo, para M(X,0:19) busque a próxima instrução na metade esquerda de M(X) se AC ≥ 0 então desvie se o número em AC não for negativo, para M(X,20:39) busque a próxima instrução na metade direita de M(X) Some M(X) a AC; resultado em AC AC ← AC + M(X) Some |M(X)| a AC; resultado em AC AC ← AC + |M(X)| AC ← AC – M(X) AC ← AC – |M(X)| Subtraia M(X) de AC; resultado em AC Subtraia |M(X)| de AC; resultado em AC Multiplique M(X) por MQ; coloque os bits mais significativos do resultado em AC e os menos signif. em MQ Divida AC por M(X); coloque o quociente MQ,AC ← AC ÷ M(X) em MQ e o resto em AC Multiplique AC por 2; i.e., desloque em AC ← AC x 2 um bit à esquerda Divida AC por 2; i.e., desloque em um bit AC ← AC ÷ 2 à direita de M(X,8:19) ← AC(28:39) Substitua campo de endereço à esquerda de M(X) pelos 12 bits mais à direita de AC M(X,28:39) ← AC(28:39) Substitua campo de endereço à direita de M(X) pelos 12 bits mais à direita de AC AC,MQ ← MQ * M(X) Modificação endereço Tabela 3.3 - Conjunto de instruções do computador IAS As instruções de transferência possibilitam a transferência entre posições de memória e registradores da UCP, sem que haja modificação nas informações (exceto nos casos em que é alterado o sinal). As instruções de desvio fazem com que seja buscado um novo endereço, para a próxima instrução, na memória (se atendida uma condição, no caso do desvio condicional). Estas instruções portanto permitem a alteração da seqüência de execução de um programa. 3-16 As instruções aritméticas fornecem os comandos básicos de processamento de informações ao computador. As instruções de modificação de endereço permitem o cômputo de endereços na unidade lógico-aritmética e sua inserção posterior em instruções armazenadas na memória. Esta propriedade permite que o computador altere suas próprias instruções, o que se constitui em uma característica importante das máquinas de programa armazenado. 3 . 6 Arquiteturas de 4, 3, 2, 1 e 0 endereços Enquanto o EDVAC trabalhava basicamente com 4 endereços, o IAS apresentava somente um endereço. Mesmo assim, ambas arquiteturas possuíam as mesmas capacidades. Para ilustrar como isto é possível, e também para analisar como a quantidade de endereços de memória influencia nas instruções e na própria arquitetura, são exemplificadas a seguir máquinas de 4 endereços (como o EDVAC), de 3 endereços, de 2 endereços, de 1 endereço (como o IAS) e até as máquinas de zero endereços (por endereço entende-se uma referência à memória). Ao invés de uma análise detalhada de arquiteturas típicas de cada caso, será apresentada unicamente a programação de uma equação aritmética: A = ((B + C)*D + E – F) / (G * H) As letras A até H denotam posições de memória (endereços), e supõe-se que a arquitetura analisada possui as quatro operações aritméticas (ADD para soma, SUB para subtração, MUL para multiplicação e DIV para divisão). O formato exato de cada instrução, assim como os tamanhos de operandos e instruções são irrelevantes nesta análise. 3 . 6 . 1 Arquitetura de 4 endereços Em uma arquitetura típica de 4 endereços, as instruções apresentam o formato OP E1 E2 E3 E4 onde OP representa a operação a ser realizada, E1 e E2 indicam a localização dos dois operados fontes desta operação, E3 indica a localização do operando destino (onde o resultado deve ser armazenado) e E4 indica o endereço onde está localizada a próxima instrução a ser executada. Note-se que a ordem destes 4 endereços dentro da instrução pode variar. Um programa que execute o cálculo da equação acima pode ser visto a seguir. Note-se que este programa foi otimizado para evitar o uso de outras posições adicionais de memória, e representa somente uma entre inúmeras implementações possíveis. Endereço e1 e2 e3 e4 e5 e6 e7 Instrução ADD B C A e2 MUL A D A e3 ADD A E A e4 SUB A F A e5 DIV A G A e6 DIV A H A e7 HALT Comentário Soma B com C, resultado em A; vai para e2 Multiplica A por D, resultado em A; vai para e3 Soma A com E, resultado em A; vai para e4 Subtrai F de A, resultado em A; vai para e5 Divide A por G, resultado em A; vai para e6 Divide A por H, resultado final em A; vai para e7 Fim do programa Figura 3.11 - Programa em uma máquina de 4 endereços Como cada instrução traz implicitamente o endereço da próxima instrução, não existe a necessidade de instruções explícitas de desvio (como JUMP e BRANCH). Além disto, uma arquitetura de 4 endereços permite potencialmente a execução de uma operação de 3-17 manipulação de dados e uma operação de desvio do fluxo do programa em uma única instrução. Entretanto, a prática demonstrou que normalmente os programas eram escritos sequencialmente, isto é, uma instrução seguindo a anterior. Com isto modificou-se o mecanismo de sequenciamento das instruções, o que deu origem às arquiteturas de três endereços. 3 . 6 . 2 Arquitetura de 3 endereços Em uma arquitetura típica de 3 endereços, as instruções apresentam o formato OP E1 E2 E3 onde OP representa a operação a ser realizada, E1 e E2 indicam a localização dos dois operados fontes desta operação e E3 indica a localização do operando destino. Para localizar a próxima instrução a ser executada, criou-se um registrador específico, denominado de PC (do inglês Program Counter, veja-se seção 3.3.3). Implicitamente, o PC aponta para o endereço seguinte ao da instrução sendo executada. Assim, o programa fica: Endereço e1 e1+1 e1+2 e1+3 e1+4 e1+5 e1+6 Instrução ADD B C A MUL A D A ADD A E A SUB A F A DIV A G A DIV A H A HALT Comentário Soma B com C, resultado em A; incrementa PC Multiplica A por D, resultado em A; incrementa PC Soma A com E, resultado em A; incrementa PC Subtrai F de A, resultado em A; incrementa PC Divide A por G, resultado em A; incrementa PC Divide A por H, resultado final em A; incrementa PC Fim do programa Figura 3.12 - Programa em uma máquina de 3 endereços Com a redução de 4 para 3 endereços, existe uma redução do tamanho da instrução e uma consequente redução do tamanho da memória necessária para armazenar os programas. Naturalmente, perdeu-se um grau de liberdade: a determinação do endereço da próxima instrução. Existe agora a necessidade de instruções explícitas de desvio (como JUMP e BRANCH), e não se pode mais executar simultaneamente uma operação de manipulação de dados e uma operação de desvio do fluxo do programa em uma única instrução. A economia de memória, assim como a obrigatoriedade de desenvolvimento de programas sequenciais (mais fáceis de serem testados, entendidos e corrigidos), entretanto, compensavam este grau de liberdade perdido. Instruções de três endereços, entretanto, ainda consomem muita memória. Além disto, observando-se o programa acima, nota-se que na maioria da vezes um dos operandos fonte e o operando destino indicam o mesmo endereço (como é o caso do operando A). Com isto modificou-se a maneira de indicar os operandos, o que deu origem às arquiteturas de dois endereços. 3 . 6 . 3 Arquitetura de 2 endereços Em uma arquitetura típica de 2 endereços, as instruções apresentam o formato OP E1 E2 onde OP representa a operação a ser realizada, E1 e E2 indicam a localização dos dois operados fontes desta operação e E1 também indica a localização do operando destino. Assim, E1 tem dupla função, e não são mais possíveis instruções com três operandos 3-18 distintos. Isto permite uma maior redução nos bits necessários para especificar os endereços dos operandos, mas introduz uma restrição séria: o resultado da operação será armazenado no endereço de um dos dois operandos fonte, ou seja, um destes dois operandos será necessariamente alterado. Esta restrição foi contornada com a criação de uma classe extra de instruções, as instruções de movimentação de dados, que permitem copiar operandos de uma posição para outra, conforme pode ser visto no programa a seguir: Endereço e1 e1+1 e1+2 e1+3 e1+4 e1+5 e1+6 e1+7 Instrução MOV A B ADD A C MUL A D ADD A E SUB A F DIV A G DIV A H HALT Comentário Move B para A Soma A com C, resultado em A Multiplica A por D, resultado em A Soma A com E, resultado em A Subtrai F de A, resultado em A Divide A por G, resultado em A Divide A por H, resultado final em A Fim do programa Figura 3.13 - Programa em uma máquina de 2 endereços Comparando-se este programa com o da arquitetura de três endereços, nota-se que a primeira instrução (ADD B C A) foi substituída por outras duas, uma de movimentação (MOV A B) e outra de manipulação de dados (ADD A C). O resultado final é o mesmo, mas o programa possui mais instruções. Entretanto, as instruções são menores, o que em termos líquidos proporciona uma grande economia de bits. Com a criação de registradores especiais, pode-se reduzir ainda mais o número de endereços, criando-se então as arquiteturas de um endereço. 3 . 6 . 4 Arquitetura de um endereço Em uma arquitetura típica de um endereço, as instruções apresentam o formato OP E1 onde OP representa a operação a ser realizada e E1 indica a localização de um operando de memória (normalmente um dos operandos fontes da operação). O outro operando é implicitamente assumido como sendo um registrador específico, o acumulador (normalmente abreviado por AC, veja-se seção 7.2). O Acumulador assume os papéis de um dos operandos fonte e do operando destino. Em relação às arquiteturas de dois endereços, agora as instruções de movimentação de dados devem ser subdivididas de acordo com o sentido da transferência: se da memória para o acumulador (LDA, de LoaD Acumulator), ou se do acumulador para a memória (STA, de STore Acumulator).O programa exemplo deve ser conveniente modificado para refletir esta situação (observe-se a instrução extra no fim do programa): Endereço e1 e1+1 e1+2 e1+3 e1+4 e1+5 e1+6 e1+7 e1+8 Instrução LDA B ADD C MUL D ADD E SUB F DIV G DIV H STA A HALT Comentário Move B para Acumulador Soma Acum. com C, resultado no Acumulador Multiplica Acum. por D, resultado no Acumulador Soma Acum. com E, resultado no Acumulador Subtrai F do Acum., resultado no Acumulador Divide Acum. por G, resultado no Acumulador Divide Acum. por H, resultado no Acumulador Armazena Acum. no endereço de A Fim do programa Figura 3.14 - Programa em uma máquina de um endereço 3-19 Comparando-se este programa com o da arquitetura de três endereços, nota-se que existem duas instruções adicionais de transferência de dados, uma no início do programa (LDA B) e outra no fim (STA A). A grande vantagem deste tipo de arquitetura está na economia dos acessos à memória: praticamente cada operando foi lido ou escrito uma única vez, o que não ocorre nas arquiteturas anteriores. Este é justamente o papel dos registradores locais (ou acumuladores): permitir que resultados intermediários ou dados muito utilizados não precisem ser lidos ou escritos da memória a cada vez que forem utilizados. 3 . 6 . 5 Arquitetura de zero endereços Em uma arquitetura típica de zero endereços, as instruções apresentam o formato OP ou seja, não existe nenhuma referência explícita a endereços de memória onde estejam localizados os operandos. Uma possível solução para determinar a posição dos operandos é colocá-los em uma região específica de memória, com determinado mecanismo de acesso. Uma estrutura muito utilizada para estes fins é uma pilha: os operandos são sempre retirados do topo da pilha, e o resultado da operação sempre é colocado no topo da pilha. Para facilitar a operação desta estrutura de pilha, as equações são escritas utilizando-se notação polonesa reversa, onde o símbolo da operação é escrito após os dois operandos. Assim, por exemplo, A+B seria escrito AB+. Com isto, a equação exemplo fica: HGFEDCB+*+–// E o programa que a implementa seria: Endereço e1 e1+1 e1+2 e1+3 e1+4 e1+5 e1+6 e1+7 e1+8 e1+9 e1+10 e1+11 e1+12 e1+13 e1+14 Instrução PUSH H PUSH G PUSH F PUSH E PUSH D PUSH C PUSH B ADD MUL ADD SUB DIV DIV POP A HALT Comentário Coloca H no topo (atual) da pilha Coloca G no topo da pilha Coloca F no topo da pilha Coloca E no topo da pilha Coloca D no topo da pilha Coloca C no topo da pilha Coloca B no topo da pilha Topo da pilha recebe B+C (B e C são retirados da pilha) Topo recebe (B+C)*D Topo recebe (B+C)*D + E Topo recebe (B+C)*D + E - F Topo recebe ((B+C)*D + E - F)/G Topo recebe ((B+C)*D + E - F)/G*H Topo da pilha é armazenado em A Fim do programa Figura 3.15 - Programa em uma máquina de zero endereços Note-se que duas instruções (PUSH e POP) na realidade utilizam endereços. Estas são, entretanto, as duas únicas instruções que necessitam referenciar endereços, e são somente operações de transferência de dados. Uma arquitetura pura de zero endereços não apresenta vantagens marcantes sobre arquiteturas de um ou dois endereços, e por causa disto não são muito difundidas. Os computadores atuais, entretanto, possuem estruturas do tipo pilha para propósitos específicos. Isto será assunto de outras disciplinas. 3-20