Como os computadores funcionam: uma explicação das bases


Começando com uma pressionada de tecla

Você pressiona a letra ‘A’ no seu teclado.

Em menos de 1 milissegundo, o caractere aparece na tela.

Parece simples? Na realidade, nesse 1 milissegundo, um sinal elétrico atravessa pelo menos 6 camadas de abstração, passa por dezenas de componentes de hardware e cruza vários barramentos para completar essa interação “simples”.

A essência dos computadores não é o cálculo, mas a abstração.

Cada camada esconde a complexidade abaixo e expõe apenas uma interface limpa para a camada superior. É por causa dessas abstrações que os programadores podem escrever código em linguagens de alto nível sem se preocupar com como os elétrons fluem pelos transistores.

Hoje, traçamos a jornada completa de um sinal de pressionada de tecla, vendo como os computadores, camada após camada de abstração, transformam uma ação física em um caractere na tela.

Primeira camada: do sinal físico ao código de varredura

Imagem

O que você pressiona não é uma letra, mas um interruptor.

Debaixo de cada tecla do teclado há um interruptor mecânico. Quando você pressiona a tecla ‘A’, o interruptor fecha e a corrente flui. Esta é a realidade física mais básica — apenas ligado e desligado, nenhum ‘A’.

O trabalho do controlador do teclado é traduzir esse sinal físico em números que o computador possa entender.

Como ele faz isso?

Varredura matricial

Mais de 100 teclas em um teclado. Se cada uma tivesse seu próprio fio conectado ao computador, o cabo do teclado seria mais grosso que seu dedo. Então o teclado usa um design inteligente: a varredura matricial.

Imagine um tabuleiro de xadrez, com linhas de fileiras e linhas de colunas se cruzando. Cada tecla está em uma interseção. O controlador energiza rapidamente cada fileira e detecta se há corrente em cada coluna. Se a coluna 5 detecta corrente quando a fileira 3 está energizada, isso significa que a tecla na fileira 3, coluna 5 foi pressionada.

É daqui que vem o código de varredura (scan code) — um número que representa a posição de uma tecla.

Pressionar ‘A’ pode gerar o código de varredura 0x1E. Soltar ‘A’ gera 0x9E (com um bit alto adicional indicando “liberação”).

Primeira camada completa: ação física → codificação digital.

Mas ainda não acabou. O código de varredura ainda está no buffer interno do teclado, esperando para ser enviado.

Segunda camada: do dispositivo de E/S à memória

Imagem

O código de varredura precisa chegar à CPU, mas a CPU não pode ficar esperando a entrada do teclado.

A CPU opera a bilhões de operações por segundo; a entrada do teclado chega a dezenas de entradas por segundo. Se a CPU verificasse “há entrada do teclado?” antes de cada instrução, 99,9999% do seu tempo seria desperdiçado.

Qual é a solução? O mecanismo de interrupção.

Interrupções: a versão de hardware de “me ligue quando estiver pronto”

A filosofia de design das interrupções reflete a vida cotidiana: você não liga para o entregador a cada 5 minutos perguntando “minha encomenda chegou?” Em vez disso, o entregador liga para você quando chega.

Após o controlador do teclado gerar um código de varredura, ele envia um sinal de Requisição de Interrupção (IRQ) para a CPU.

Esse sinal passa pelo controlador de interrupções (8259A ou seu equivalente moderno) e recebe um número de interrupção. O teclado é tipicamente IRQ1, número de interrupção 0x21.

Após executar cada instrução, a CPU verifica se há sinais de interrupção. Se houver um, ela pausa seu trabalho atual e trata a interrupção.

A tabela de vetores de interrupção

Como a CPU sabe como tratar uma interrupção do teclado?

Na memória, há uma Tabela de Vetores de Interrupção (Interrupt Vector Table) que armazena o endereço da rotina de tratamento para cada número de interrupção. É como uma lista telefônica: o número de interrupção 0x21 corresponde ao endereço do manipulador do teclado.

Quando a CPU recebe uma interrupção do teclado:

  1. Empilha o Contador de Programa (PC), o registro de estado, etc.
  2. Consulta a tabela usando o número de interrupção para encontrar o endereço do manipulador
  3. Salta para o manipulador e o executa

O manipulador do teclado lê o código de varredura através de uma porta de E/S (tipicamente 0x60) e então o armazena no buffer do teclado na memória.

Segunda camada completa: evento de E/S → dados na memória.

Agora o código de varredura está seguro na memória. Mas ainda é um código de varredura, não o caractere ‘A’.

Terceira camada: do código de varredura ao caractere

Imagem

O código de varredura 0x1E representa “a posição da tecla A no teclado”, não o caractere ‘A’.

Por quê? Porque a mesma tecla pode representar caracteres diferentes em teclados de diferentes países. Americanos pressionam e obtêm ‘A’; franceses pressionam e obtêm ‘Q’ (a distribuição do teclado deles é diferente).

O sistema operacional é responsável por converter os códigos de varredura em caracteres.

O subsistema de entrada

Os sistemas operacionais modernos têm um Subsistema de Entrada (Input Subsystem), que gerencia:

  1. Ler códigos de varredura do buffer do kernel
  2. Convertê-los em caracteres com base na distribuição atual do teclado
  3. Gerenciar teclas modificadoras (Shift+A = ‘A’ maiúsculo, Ctrl+C = comando copiar)
  4. Entregar o caractere à janela ativa

Essa conversão envolve uma tabela de mapeamento de distribuição do teclado. O registro do Windows contém HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts, que armazena o mapeamento para vários idiomas.

Após a conversão, o caractere ‘A’ é colocado em uma fila de mensagens, esperando para ser lido pela aplicação.

Terceira camada completa: codificação dependente de hardware → codificação unificada de caracteres.

Quarta camada: do caractere ao pixel

Imagem

A aplicação recebe o caractere ‘A’ e precisa exibi-lo na tela.

Mas o que você vê não é um caractere — são pixels.

Um monitor só entende pixels — de que cor cada ponto é. O caractere ‘A’ é um padrão formado por um conjunto de pixels, armazenado em um arquivo de fonte.

Renderização de fontes

Quando você digita ‘A’, a aplicação vai:

  1. Procurar o arquivo de fonte (ex. Microsoft YaHei, SimSun)
  2. Obter a descrição do glifo para ‘A’ (curvas vetoriais ou bitmap)
  3. Escalar o glifo de acordo com o tamanho da fonte
  4. Rasterizar: converter as curvas vetoriais em uma grade de pixels
  5. Aplicar anti-aliasing para bordas mais suaves

Esses dados de pixel são escritos na memória de vídeo (VRAM), que é a memória na placa de vídeo.

Da VRAM para a tela

O controlador de exibição na placa de vídeo lê dados da VRAM 60 vezes por segundo (60 Hz), converte em um sinal de vídeo e o envia ao monitor.

O monitor recebe o sinal, controla a cor de cada pixel, e você vê o caractere ‘A’.

Quarta camada completa: codificação de caracteres → matriz de pixels.

Quinta camada: como a CPU executa essas instruções

Imagem

Todas as operações mencionadas acima — varredura, interrupções, conversão, renderização — precisam ser executadas pela CPU.

Como a CPU executa instruções?

O ciclo de instrução: buscar-decodificar-executar

A execução de uma instrução tem três estágios:

  1. Buscar (Fetch)

    • O Contador de Programa (PC) armazena o endereço da próxima instrução
    • Envia o endereço à memória, recupera a instrução
    • Armazena a instrução no Registro de Instrução (IR)
  2. Decodificar (Decode)

    • A unidade de controle analisa o código de operação da instrução
    • Determina qual operação realizar (adição? carregamento? salto?)
    • Determina onde estão os operandos
  3. Executar (Execute)

    • A Unidade Lógica e Aritmética (ULA) realiza o cálculo
    • Ou acessa a memória para ler/escrever dados
    • Atualiza o Contador de Programa

Então repete.

Um exemplo

Suponha que a CPU precise executar ADD R1, R2, R3 (somar os valores em R2 e R3, armazenar em R1):

  1. Buscar: ler o código de máquina para esta instrução da memória
  2. Decodificar: reconhecer isto como uma instrução de adição, operandos em R2 e R3
  3. Executar: a ULA envia os valores de R2 e R3 ao somador, escreve o resultado em R1

Cada instrução é concluída em nanossegundos.

Quinta camada completa: linguagem de alto nível → instruções de máquina → sinais elétricos.

O custo da abstração

Abstração não é gratuita.

Cada camada de abstração tem um custo de desempenho:

  • Varredura do teclado: alguns microssegundos
  • Tratamento de interrupção: dezenas de microssegundos
  • Conversão do SO: centenas de microssegundos
  • Renderização de fontes: alguns milissegundos
  • Escrita na VRAM: alguns microssegundos

Juntos, isso é a “latência de entrada” (input lag) que você experimenta, tipicamente entre 10 e 50 milissegundos.

Para uma pessoa comum, essa latência é insignificante. Mas para jogadores de e-sports, é uma diferença de vida ou morte. É por isso que eles usam teclados mecânicos (acionamento mais rápido), monitores de alta taxa de atualização (144 Hz ou mais) e conexões com fio (sem fio adiciona latência extra).

Uma conclusão

A essência dos computadores é abstração: encapsular complexidade, expor apenas uma interface simples.

A jornada de um sinal de pressionada de tecla:

Interruptor físico → código de varredura → interrupção → buffer de memória → codificação de caracteres → fila de mensagens → renderização de fontes → VRAM → pixel

Cada camada faz apenas uma coisa: receber a saída simplificada da camada inferior, processá-la e fornecer uma interface simplificada para a camada superior.

É precisamente essa abstração em camadas que permite aos humanos dominar sistemas computacionais incrivelmente complexos.

Programadores não precisam saber como a varredura do teclado funciona — eles só precisam ler o valor de retorno de getchar().

Programadores não precisam saber como a placa de vídeo renderiza — eles só precisam chamar a função DrawText().

O poder da abstração é tornar a complexidade gerenciável.

Imagem