2011/01/15

Como Funciona um CPU?

No outro dia mostrei-vos uma simulação visual do que acontece dentro de um CPU, e prometi escrever um artigo que explicasse de forma simplificada o que se passa no seu interior a nível de programação. Pois bem... aqui está ele!

Por debaixo de todos os plásticos, peças metálicas e vidro à superfície de um computador, esquecendo todos os 1001 periféricos e componentes acessórios, esconde-se o CPU - o "coração" e cérebro de todo este sistema!

Se querem ficar a conhecê-lo um pouco melhor... venham daí... mas aviso-vos que o artigo é grandito! :)




O CPU

O CPU é, como o seu próprio nome indica - Central Processing Unit - um processador de instruções.

No seu interior, bits e bytes são processados sem parar, num contínuo ciclo indiferente à linguagem de programação que lhes deu origem: no que ao CPU diz respeito há apenas uma única linguagem... o código máquina. Estranhos códigos binários de zeros e uns que afastarão a maioria dos programadores, mas que são a verdadeira "língua" que o CPU entende. Toda e qualquer linguagem de programação tem que ser, de uma forma ou de outra, compilada ou interpretada, até que se torne em algo que o CPU entenda.

Para todos aqueles que mesmo assim gostam de trabalhar com o CPU a este nível, existe em versão mais humanizada... o Assembly/Assembler/ASM. Representação simbólica desse código máquina e que permite mais facilmente visualizar, manipular e programar!

Por exemplo, em vez de terem que lidar com isto:
11001010 00000001 00000000 00000000
O Assembly permite que isso se traduza em algo mais amigável, como isto:
ld %r4,%r5


Antes que comecem a deitar a mão à cabeça, vamos lá simplificar a coisa: o CPU tem no seu interior vários registos onde guarda várias informações. Uma delas, talvez a mais importante, é aquela que lhe diz qual a posição da próxima instrução a executar. É esse registo que serve de fio condutor a tudo o que será executado pelo CPU.


A Arquitectura

Mas - antes de prosseguirmos - há ainda um factor fundamental: a arquitectura do sistema em questão. É que um CPU por si só, não será capaz de fazer grande coisa... São necessários alguns componentes essenciais para que ele faça algo; componentes que estão ligados com o CPU através de barramentos (Bus), e acedidos através de endereços.
Há vários tipos de arquitectura, mas para os efeitos de hoje, vamos centrar-nos na que é mais utilizada pelos CPUs actuais: a arquitectura de Harvard modificada.

Afinal, não serviria de muito ter um CPU sem sítio onde pudessemos guardar o nosso programa a executar, nem forma de sinalizar para o exterior o seu resultado, pois não?


O Funcionamento

Imaginemos então que alguém ligava o nosso processador imaginário: a electricidade começa a fluir; o CPU "acorda", e começa a procurar o que fazer, e dirige-se à instrução número zero. Executa-a, passa para a instrução seguinte, e assim sucessivamente até que alguém o desligue... ou algo de muito grave aconteça (como por exemplo, aquecer a tal ponto que derreta! :)

Basicamente, é apenas isto. A sério!

Dependendo do tipo de CPU, este poderá ter um conjunto de instruções que vão de apenas algumas dúzias de instruções, às centenas!
E voltando à ideia original que me fez escrever este artigo, se alguma vez olharam para um qualquer pedaço de assembly, de qualquer processador, torna-se evidente que grande parte das instruções existentes na maioria dos programas, são movimentações de pedaços de informação de um lado para o outro e operações aritméticas.

Moves, adds, ands, ors, etc. etc. etc. Tudo instruções que recorrentemente encontrarão em toda e qualquer listagem de assembly de todo e qualquer CPU.

Era precisamente isto que me fazia uma enorme confusão - e que servia de base ao pensamento de que "um computador não passava de uma máquina calculadora"!

A "calculadora"

E posso dizer-vos que isto foi algo que me intrigou durante bastante tempo... Como é que mover informação de um lado para o outro, ou fazer umas contas de somar e subtrair, poderia fazer com que a tecla que eu carregasse aparecesse escrita no ecrã? Como é que isso poderia criar uma fotografia a aparecer no monitor?

Pois bem, o segredo está no tal barramento que permite que o CPU tenha acesso a outros dispositivos.

Voltando ao nosso sistema imaginário, poderíamos definir que o endereço de 0 a 1000 consistiria num espaço de memória onde se iriam guardar as instruções do nosso programa. Mas que o endereço 1001 seria especial: nesse local seria colocado o valor da tecla que fosse carregada no teclado. E no endereço 1002, seria um endereço que, dependendo do seu valor, controlaria um ruidoso buzzer, o valor 0 significaria desligado, o valor 1 faria barulho.

Já estão a ver o que isto permitiria? Poderíamos fazer um programa e guardá-lo nos endereços de 0 a 1000, que - por exemplo - pudesse fazer barulho sempre que se carregasse numa determinada tecla. Numa sequência de instruções que seria semelhante à seguente:

Endereço - Instrução
0 - Ler o valor do endereço 1001 (teclado)
1 - Ver se o valor lido é igual à tecla "B"
2 - Se sim, então colocar o valor 1 no endereço 1002 (ligando o buzzer)
3 - Se não, colocar o valor 0 no endereço 1002 (desligando o buzzer)
4 - Saltar de novo para o endereço 0


Estão a começar a perceber o esquema?...


Há muito mais que o CPU...

Sim, mais que saber programar um CPU, torna-se fundamental conhecer todo o sistema em que está inserido. É preciso saber em que endereços estão que equipamentos, etc. etc. É por isso mesmo que um programa em código máquina criado para um smartphone da marca "A", não funcionará noutro da marca "B" mesmo que tenha o mesmo processador. É que nesse outro smartphone, os dados do teclado, ecrã, e outros periféricos, poderão estar em endereços completamente diferentes!

Daí que haja a necessidade de compatibilizar os equipamentos: e foi esse um dos grandes feitos dos computadores "PC Compatíveis". Criar uma base estável, que garantia que um programa feito para correr num deles, correria em todos os que fossem compatíveis.
Senão, imaginem a loucura que seria programarem para computadores, onde cada um tinha a memória, inputs e outputs, e tudo o resto, em locais diferentes?


Mas, ainda não perceberam lá muito bem como é que de assembler se pode chegar a um fabuloso jogo 3D num ecrã de alta-resolução?

O "segredo" é que um computador consiste num infindável número de módulos, e o CPU já não está sozinho no que toca a fazer todas as operações. Actualmente, temos placas gráficas com GPUs que são tão - ou mais - complexos que um CPU; controladores de discos que se encarregam de transferir dados quase sem intervenção do CPU; e muito mais.
Sim, tempos houve em que tinha que ser o CPU a preocupar-se em colocar o motor do drive de disquetes a girar, a posicionar a cabeça de leitura/gravação no sector respectivo, e ler ou escrever dados... Tudo graças aos tais endereços de input/output que lhe davam controlo sobre todos esses pequenos motores.

Aliás, é algo com que ainda hoje se deparam todos aqueles que gostam de brincar com Arduinos: portas de entrada, portas de saída, e tudo o mais que serve de base a todos os complexos equipamentos que temos hoje.


Os Drivers

Nos "PCs", parte dessa complexidade evoluiu na forma de "drivers". Alguma vez pensaram no que é efectivamente um driver? Aquele pedaço de software que frequentemente são obrigados a instalar sempre que colocam uma peça nova no vosso sistema (seja ela uma placa gráfica ou uma câmara ou impressora)?

Basicamente, temos um sistema "compatível", onde - por exemplo, e no caso de uma placa gráfica - se define que existe um conjunto de funções para concretizar um objectivo, por exemplo: pintar um pixel nas coordenadas X, Y, na cor pretendida.
Quem faz os programas para esse sistema, sabe que pode chamar essa função... sem nunca se ter que preocupar qual a placa gráfica que irá existir no computador do utilizador, que tipo de GPU ela utiliza, ou em que endereço ela está. Cabe ao fabricante da placa criar o "driver" que serve de intermediário, e que sabe que - quando alguém chamar aquela função de pintar um pixel, irá movimentar todos os bits necessários para os locais respectivos, de forma a fazer com que no ecrã surja o resultado pretendido.

Sim, como podem imaginar, mesmo uma operação simples pode originar milhares ou milhões de operações que terão que ser processadas pelo CPU.
Agora mesmo, sempre que carrego numa tecla... há um processo que se encarrega de a ler, enviar para a janela do programa correcta, mas ao mesmo tempo está a ver se a palavra está bem escrita... desenhando-a no ecrã, com uma linha a vermelho em caso de erro... enquanto na barra inferior o relógio é actualizado de minuto a minuto, e na janela do lado informações continuam a fluir, ao mesmo tempo que música continua a tocar noutra janela...
E é por isso que muitas vezes, mesmo os CPUs que trabalham a frequências de Gigahertzs parecem não ser tão rápidos como desejaríamos....


Já agora, essa frequência do CPU (assim de modo muito geral) indica a velocidade com que o CPU é capaz de executar uma instrução.

E já agora, ficam também a conhecer a diferença entre CPUs que agora estão cada vez mais na moda: os CISC e os RISC.


CISC e RISC

Lembram-se das tais instruções que podemos dar ao CPU para eles executar? Pois bem... há CPUs e CPUs; e dividem-se principalmente em duas grandes famílias: os CISC (Complex Instruction Set Computing) e os RISC (Reduced Instruction Set Computing).

Com a evolução da microelectrónica, os CPUs foram ficando cada vez mais complexos e evoluídos. O tal número de instruções que um CPU podia executar não parava de crescer e aumentar.
Começam a surgir instruções que permitiam, num só comando, ir buscar um valor ao endereço de memória "X", ir buscar outro ao endereço "Y", somar ambos os valores e colocar o resultado no endereço "Z"!
Rapidamente, estes CPUs se tornaram em sistemas altamente complexos.

Chegou-se ao ponto - como nos casos dos nossos bem conhecidos processadores x86 (cuja evolução nos trouxe do "PC Compatível" com o seu Intel 8086 até aos mais recentes Intel Core i7 actuais) - em que os CPUs eram já tão complexos, que cada instrução era internamente subdividida em várias micro-instruções mais pequenas que eram executadas pelo CPU!

Isto fez com que alguns investigadores decidissem regressar às origens e simplificar tudo novamente, com os processadores RISC (como os tão em voga processadores ARM que tanto têm dado que falar.) A ideia era simples: simplificar e reduzir. Em vez de instruções complexas, o CPU seria apenas capaz de fazer as operações mais básicas e essenciais.

Em vez de termos uma única instrução como a que referi anteriormente, de ir buscar dois valores a dois sítios diferentes e colocar a soma num terceiro sítio; num CPU RISC temos que fazer todos esses passos expressamente:

  1. ir buscar o valor 1 e guardar num registo temporário A;
  2. ir buscar o valor 2 e colocá-lo noutro registo B; 
  3. somar o registo A com o registo B (ficando aqui o resultado); 
  4. guardar o registo B na posição de destino 3. 
Dá mais trabalho, não? Então, qual a vantagem?
A vantagem é que o CPU tem um processo de fabrico muito mais simples; e em grande parte dos casos, pode até correr mais depressa. Em vez de instruções complexas que têm que ser convertidas em microcódigo e podem demorar dezenas ou centenas de ciclos de relógio, num processador RISC quase sempre cada instrução pode ser executada num único ciclo. (É por isso mesmo que não se pode comparar directamente um CPU CISC x86 a 1Ghz, com um processador ARM RISC a 1Ghz - são coisas completamente diferentes!)

Para além disso, todo esse trabalho extra acaba por ser feito pelos compiladores, já que a programação será feita numa linguagem de mais alto nível, como C.

Até aqui relegados para papeis menos mediáticos, os CPUs RISC começam agora a mostrar todo o seu valor nos Android, iPhones e demais tablets e dispositivos mobile, onde oferecem uma eficiência que não tem sido possível igualar com os mais complexos e mais gastadores CPU Cisc.

E com tudo isto, já me alarguei um pouco do tema central, que era explicar-vos como um CPU funcionava. De qualquer forma, espero que tenha dado para ficarem com uma ideia... e se tiverem dúvidas... é só dizerem nos comentários! :)


Se chegaram até aqui, poderão querer espreitar o artigo que aborda o que é o firmware.

16 comentários:

  1. LSDI FEUP!! xD

    ResponderEliminar
  2. Obrigado. Guardado nos marcadores para futura leitura assim que haja tempo :)

    ResponderEliminar
  3. LSDI FEUP literalmente! Parecia mesmo o prof a falar!

    Grande artigo! Parabéns! :)

    ResponderEliminar
  4. Ena, que isto tem tanta letra! Vou ler mais logo, para recordar os tempos de Arquitectura de Computadores.

    ResponderEliminar
  5. Como costuma ser típico aqui... falta a(s) fonte(s).

    Pelo menos uma é fácil de conhecer... certamente que seria fácil encontrar uma versão inglesa do resto....

    Enfim... Carlinhos... é bom ganhar notoriedade, mas mantêm o bom caminho... Não abuses porque se hoje tens vários olhos, amanha isto é apenas mais um sitio (já não é??) de traduções rápidas da net para pseudo-analfabetos tecnológicos.

    Mas... boa agregadela ;)

    ResponderEliminar
  6. Um artigo muito interessante de ler! Deu para ficar com uma pequena ideia, mas continua a parecer "magia" o que acontece dentro dos computadores xD

    ResponderEliminar
  7. Parabens! Post excelente!

    ResponderEliminar
  8. Excelente artigo!
    Bastante informativo e ao mesmo tempo leve e fácil de compreender.

    ResponderEliminar
  9. Obrigado a todos os que gostaram.

    Quanto ao @Anónimo, agradecia que me indicasse as "fontes" que pensa que eu terei plagiado, considerando que este é um artigo completamente original e integralmente escrito aqui pelo "Carlinhos".

    De igual forma, não compreendo a acusação da falta de indicações "como costuma ser típico aqui", já que rara será a notícia que escrevo cá que não lá tenha um link para a fonte... (Só para confirmar que não estava a alucinar, até fui espreitar os 10 últimos posts, e em todos eles tinha links para as fontes...)

    Quanto às "traduções rápidas", quem procurar isso certamente saberá que pode contar com o Google Translate, coisa que por aqui não é usada.
    As notícias são as mesmas que muitos outros sites referem - quanto a isso não há volta a dar! - mas desde o início que as tento seleccionar e apresentar com o meu próprio cunho pessoal.
    Ao longo dos anos, sinto que os meus esforços diários tem mostrado o que valem, pelo que esse tipo de insinuações me parece estar mal direccionada... (Talvez se tenha enganado no blog a que destinava esse comentário?)

    ResponderEliminar
  10. Esta leitura decerto que me ia dar jeito na altura em que tive arquitectura de computadores na univ. Felizmente já está despachada mas é sempre bom recordar isto tendo em conta que é uma leitura que esclarece os principios envolvidos com bastante simplicidade.
    Os meus parabéns :)

    ResponderEliminar
  11. Simples, e bem explicado! Parabéns

    ResponderEliminar
  12. Obrigado Carlos, pelo artigo!
    Gostaria que o aprofunda-se mais, se possível

    ResponderEliminar
  13. Mais vale tarde que nunca. Tinha guardado o link para ler mais tarde e acabou por ser hoje no seguimento do artigo relativo ao firmware.
    A minha área é outra, mas sempre tive grande curiosidade sobre estes assuntos.
    Obrigado, continua.

    ResponderEliminar
  14. Excelente artigo.
    Parabéns.

    ResponderEliminar
  15. bem explicado,sem dificultar o entendimento, muito útil.

    ResponderEliminar
  16. Percebo pouco do assunto, mas o pouco que percebo dá para ver que você é mestrado no assunto.
    Parabéns pela iniciativa fiquei a saber mais daquilo que já sabia

    ResponderEliminar