Programando como se fosse 1982. Parte II – O Processador
Na Parte I cobrimos o cenário: a época, a máquina, o contexto. Agora é hora de descer um nível e entender como o processador realmente funciona. Onde os dados vivem, como as instruções são lidas e o que acontece a cada fração de segundo enquanto um programa roda.
Registradores: o espaço de trabalho do processador
Quando você escreve algo como x = 5 + 3 em qualquer linguagem moderna, o processador precisa pegar o 5 de algum lugar, pegar o 3 de algum lugar, somá-los e guardar o resultado. Esse “algum lugar” são os registradores.
Um registrador é um espaço de armazenamento que fica dentro do próprio processador. A RAM é um armazém enorme do lado de fora. O processador precisa se deslocar até lá para buscar qualquer coisa. Um registrador é o bolso do processador: minúsculo, mas instantâneo.
Toda operação aritmética ou lógica acontece dentro dos registradores. A RAM é só onde você guarda as coisas quando não está usando.
O MOS 6510 do Commodore 64 tinha exatamente três registradores de uso geral:
A, o Acumulador. O registrador principal. Praticamente toda operação passa por ele: somas, subtrações, operações lógicas, leitura e escrita na memória. O nome vem de acumular resultados. Se o 6510 fosse uma cozinha, o A seria a tábua de corte. Tudo passa por ali em algum momento.
X e Y, os Registradores de Índice. Funcionam como contadores e ponteiros de posição. O nome vem de índice, como o índice de um array. O i de um for loop em Python? Era exatamente esse o papel do X ou do Y no assembly. Você os usava para percorrer listas, navegar pela memória, contar iterações.
Três registradores é muito pouco, e era de propósito. Em 1975, quando o 6502 foi projetado, cada registrador custava transistores, e transistores custavam dinheiro e espaço no chip. A mentalidade de engenharia da época era fazer mais com menos. Na prática, isso significava que o programador precisava planejar com cuidado qual registrador ficaria com qual dado, e guardar temporariamente valores na RAM sempre que os três estivessem ocupados. Era como programar com apenas três variáveis disponíveis ao mesmo tempo.
O ciclo de execução: como o processador lê um programa
Aqui está algo que muda para sempre a forma como você enxerga um programa: para o processador, não existe distinção entre código e dado. Tudo na memória são bytes. O que faz um byte ser uma instrução é simplesmente o fato de o processador estar apontando para ele no momento certo.
O processador funciona num ciclo eterno e muito simples:
1. Leia o byte no endereço que o PC aponta
2. Interprete esse byte como uma instrução
3. Execute a instrução
4. Avance o PC
5. Repita
O PC aqui é o Program Counter, um registrador especial que não guarda dados do programa, mas o endereço da próxima instrução a ser executada. Seu único trabalho é dizer ao processador onde ele está no mapa de memória. É o cursor de execução.
Esse ciclo nunca para. Enquanto o C64 estiver ligado, o 6510 está repetindo esse loop milhões de vezes por segundo, lendo um byte, executando, avançando, lendo o próximo. Sem scheduler, sem sistema operacional gerenciando nada disso. Apenas o processador em modo automático, sem parar.
Quando um programa travava no C64, o que geralmente acontecia é que o PC foi parar num endereço com dados aleatórios, e o processador tentou interpretar aqueles bytes como instruções válidas. O resultado era imprevisível: às vezes a tela congelava, às vezes aparecia lixo na tela, às vezes o computador reiniciava. Não havia rede de segurança. Nenhuma mesmo.
Registradores especiais
Além do A, X e Y, o 6510 tinha mais três registradores que não guardam dados do programa, mas controlam o funcionamento do próprio processador:
O PC (Program Counter) já vimos: aponta para a próxima instrução.
O SP (Stack Pointer) aponta para o topo da pilha, uma região especial da memória usada para guardar endereços de retorno quando o programa chama uma sub-rotina. Quando você entra numa rotina e volta, é o SP que lembra de onde o programa estava antes da chamada.
O SR (Status Register) é diferente de todos os outros: em vez de guardar um número, ele guarda 8 bits independentes chamados flags, cada um com um significado específico. Um flag acende quando o resultado de uma operação é zero. Outro quando o resultado é negativo. Outro quando uma soma transbordou o limite de um byte. Esses flags são a base de toda decisão que um programa toma: os if, os loops, as comparações. Vamos explorar isso a fundo na Parte IV.
Registradores de uso geral: A X Y
Registradores de controle: PC SP SR
No próximo post saímos do processador e olhamos para o que está ao redor: a RAM, como ela é organizada em endereços, o que o hexadecimal realmente é e por que certas regiões da memória valiam ouro.