Assistindo a palestra do Rodrigo Strauss sobre Gerenciamento de Memória no Windows, surgiu a idéia de fazer alguns posts sobre o gerenciamento no nível do microprocessador, começando lá no tempo dos 8 bits.
Como vocês provavelmente sabem, o primeiro microprocessador disponível comercialmente foi o 4004 da Intel, de 4 bits. Posteriormente a Intel criou o 8008 de 8 bits, que rapidamente evoluiu para o 8080, cujas influências estão presentes até hoje nos processadores Intel.
Quando dizemos que o 8080 é um processador de 8 bits, isto se deve principalmente a duas características:
- a unidade lógica aritmética (ALU) faz diretamente operações com valores de 8 bits
- a ligação com a memória utiliza 8 bits de dados
A figura acima mostra os registradores do 8080. O programa counter (PC) e o stack pointer (SP) são registradores de 16 bits. Em quase todos os casos, o acumulador contém um dos operandos e recebe o resultado das operações aritméticas e lógicas.Os registradores B, C, D, E, H e L podem ser usados como registradores de uso geral de 8 bits. Entretanto, algumas instruções permitem tratar estes registradores aos pares (BC, DE e HL) para manipular valores de 16 bits. Como a ALU só consegue manipular 8 bits de cada vez, estas instruções precisam dar duas passadas pela ALU, sendo mais lentas.
Como dito, nas operações aritméticas e lógicas um dos operandos é normalmente o acumulador. O outro é um dos registradores gerais ou a posição de memória apontada pelo par HL. Em outras palavras, o registrador HL é usado principalmente como um ponteiro para a memória (endereçamento indireto).
As instruções que permitem manipular par de registradores como valores de 16 bits são:
- LXI carrega um valor imediado num par de registradores
- XCHG, XTHL trocam o conteúdo de HL respectivamente por DE e pelos dois bytes no topo da pilha
- SPHL carrega SP com o valor em HL
- LHLD carrega HL com o valor em duas posições consecutivas da memória
- SHLD guarda em duas posições consecutivas da memória p valor em HL
- INX e DCX respectivamente incrementam e decrementam um valor em um par de registradores
- DAD soma BC, DE, HL ou SP a HL
A rigor podemos dizer que o 8080 não possui nenhum recurso de gerenciamento de memória. O endereço determinado pelas instruções é colocado diretamente nos pinos que endereçam a memória. Não existe nenhum recurso de mapeamento, proteção ou memória virtual.
O CPM/80
O CPM/80 foi o principal sistema operacional para os computadores "sérios" de 8 bits e influenciou diretamente o MSDOS e indiretamente o Windows. (Talvez mereça um post específico no futuro).
Do ponto de vista de gerenciamente de memória, o CP/M80 era muito simples. Os primeiros 256 bytes de memória possuíam uma estrutura fixa, contendo o endereço de chamada ao sistema operacional e a linha de comando usada para executar os aplicativos (no MSDOS, esta estrutura virou o PSP - prefixo de segmento de programa). Os aplicativos em si eram sempre carregados logo em seguida (endereço 0x100); o sistema operacional em si residia no final da memória. Obviamente, o CP/M 80 suporta a execução de apenas um aplicativo de cada vez.
A chamada ao sistema era feito através de uma instrução CALL para o endereço 5. Nesta posição existia um desvio (JMP) para a primeira posição ocupada pelo CP/M, fazendo com que os endereços 6 e 7 indicassem o fim da memória disponível para o programa. Isto permitia criar um primeiro tipo de TSR (terminate and stay resident - programa que fica na memória após ter terminado do ponto de vista do sistema operacional). O programa se copiava para o fim da memória, antes do sistema operacional, colocava um JMP para o SO no seu inicio e alterava o JMP no endereço 5.
Quando armazenados em disco (em arquivos com extensão COM), os programas já estavam com os endereços reais de execução, nenhum tipo de relocação era necessária.
Ultrapassando a barreira dos 64K
De uma forma geral os aplicativos e o CP/M 80 não tinham suporte para nenhum esquema que aumentasse a capacidade de endereçamento do 8080. Este aumento exigia um hardware adicional externo ao processador para selecionar entre diversas regiões de memória que compartilham o mesmo endereço do processador. Esta técnica é chamada de chaveamento de memória.
O chaveamento de memória no CP/M 80 era usado na parte específica do equipamento, já então chamada de BIOS. No mínimo precisa ser usada para a carga do sistema operacional, mapeando uma memória não volátil no endereço zero (onde inicia a execução do 8080 e onde posteriormente é preciso ter RAM). Outra opção comum era "esconder" as rotinas de manipulação do hardware, reduzindo o BIOS e liberando mais memória para o aplicativo.
Outros processadores de 8 bits
Alguns funcionários da Intel saíram para fundar uma nova empresa, a Zilog, que lançou uma versão muito aprimorada do 8080, o Z80. Além de ser mais rápido, o Z80 possuiu várias instruções adicionais, principalmente fornecendo formas mais flexíveis de endereçamento da memória. Entretanto, os recursos de gerenciamento de memória continuaram inexistentes. O CP/M 80 e os aplicativos que rodavam sob ele não usavam as instruções adicionais, tratando o Z80 da mesma forma que um 8080.
Posteriormente a Intel lançou o 8085 que tinha apenas pequenos avanços em relação ao 8080.
Outro processador de 8 bits popular na época era o 6502 (usado no Apple I e Apple II). O conjunto de registradores e instruções do 6502 era completamente diferente, valorizando o acesso indireto à memória. O Apple II usava extensamente a técnica de chaveamento de memória, inicialmente para as rotinas de tratamento das placas nos slots e posteriormente para aumento da capacidade gráfica e da memória disponível.