# E/S mapeada em memória

    Traduzido do inglês em out/2010
E/S mapeada em memória (em inglês, memory-mapped I/O) ou E/S mapeada em portas (em inglês, port-mapped I/O ou port I/O) são dois métodos complementares de executar entrada/saída entre a CPU e os dispositivos periféricos no computador. Outro método, não discutido nesse artigo, é usar um processador dedicado de E/S (comumente conhecido como canal em computadores mainframe) que executa suas próprias instruções.
O método de mapeamento de E/S em memória utiliza a via de endereços para endereçar tanto a memória quanto os dispositivos de E/S e as instruções da CPU usadas para acessar a memória também são usadas para acessar os dispositivos. Para acomodar os dispositivos de E/S áreas do espaço endereçável da CPU devem ser reservadas para E/S. A reserva de espaço pode ser temporária (o Commodore 64 podia trocar entre seus dispositivos de E/S e a memória regular) ou permanente. Cada dispositivo de E/S monitora a via de endereçamento da CPU e responde a qualquer acesso da CPU ao espaço de endereço destinado ao dispositivo, conectando a via de dados ao registrador do hardware do dispositivo desejado.
E/S mapeada em porta utiliza uma classe especial de instruções do processador. Isto é normalmente encontrado em processadores intel , especificamente as instruções IN e OUT, que podem escrever de um a quatro bytes (outb, outw, outl) em um dispositivo de E/S. Estes dispositivos possuem um espaço de endereços separado da memória geral, implementado por um pino extra de E/S na interface da CPU ou por um barramento inteiro dedicado a entrada/saída. Por esta área de memória, dedicada a E/S, ser isolada da memória principal ela é, às vezes, chamada de E/S isolada.
O acesso direto à memória (DMA) de um dispositivo não é afetado por esses métodos de comunicação CPU-dispositivo, nem pelo mapeamento em memória. Isto porque o DMA é, por definição, algo distinto da comunicação com a CPU.
A Interrupção de Hardware é outra forma de comunicação entre a CPU e dispositivos periféricos, mas, por várias razões, é tratada separadamente: ela é iniciada pelo dispositivo, enquanto o método descrito acima é iniciado pela CPU; é unidirecional, pois os sinais de informação fluem somente do dispositivo para a CPU; cada interrupção carrega somente um bit de informação, com um significado fixo, dizendo algo como "um evento que requer atenção ocorreu num dispositivo dispositivo, nesta linha de interrupção".

## Vantagens relativas dos dois métodos de E/S

A principal vantagem de se utilizar E/S mapeada em memória é em CPUs com a capacidade de endereçamento limitada. Como a E/S mapeada em portas separa as o acesso de E/S do acesso de memória, o espaço para endereçamento pode ser usado inteiramente para a memória. Além disso, se torna evidente para uma pessoa lendo em linguagem assembly (ou mesmo analisando o código de máquina), a ocorrência de E/S, pela utilização das instruções específicas para este fim.
Se os barramentos de dados e endereço forem compartilhados, as operações de E/S podem deixar o acesso a memória mais lento. Isto porque normalmente os dispositivos periféricos são muito mais lentos que a memória principal. Em algumas arquiteturas E/S mapeada em memória se dá por um barramento de E/S dedicado, atenuando o problema.
Além desta, há duas grandes vantagens de se utilizar o mapeamento em memória de E/S. Uma delas é que, descartando a complexidade extra trazida pela porta E/S, a CPU precisa menos lógica interna e, portanto, é mais rápida, é mais fácil de construir, é mais barata, consome menos energia e pode ser fisicamente menor; isto segue as diretrizes principais de um RISC e é também vantajoso em sistemas embarcados. A outra vantagem é que por serem utilizadas instruções normais de memória para endereçar dispositivos, todos os métodos de endereçamento da CPU estarão diponíveis para E/S tanto quanto para a memória comum e as instruções que efetuam uma operação da ULA diretamente em um operando - carregando o operando da memória, armazenando o resultado na memória, ou ambos - podem também ser utilizadas com registradores de E/S. Em contraste, instruções de E/S mapeada em memória são extremamente restritas, frequentemente realizando apenas leitura e armazenamento entre registradores da CPU e portas de E/S, para que, por exemplo, ao se adicionar uma constante ao registrador de um dispositivo E/S mapeada em porta sejam necessárias três instruções de uma vez: ler a porta para um registrador da CPU, somar a constante ao registrador e escrever o resultado na porta novamente.
À medida que processadores 16-bit se tornaram obsoletos e foram substituídos por 32-bit e 64-bit para o uso geral, reservar grandes intervalos de endereços de memória para E/S não é mais um problema, já que o espaço para endereçamento de memória pelo processador é muito maior do que o necessário por todos os dispositivos de E/S e a memória utilizada por um sistema juntos. Assim, frequentemente é muito mais prático utilizar as vantajens dos benefícios do mapeamento de E/S em memória. No entanto, mesmo com o espaço para endereçamento não sendo mais um problema, nenhum método de mapeamento de E/S é universalmente superior ao outro, e haverá casos em que usar a E/S mapeada em porta será ainda preferível.
Uma razão final por que a E/S mapeada em memória é preferível em arquiteturas x86 é que as instruções que realizam a E/S baseada em portas são limitadas a poucos registradores: EAX, AX e AL são os únicos registradores dos quais se podem ser lidos ou onde podem ser escritos dados por essas instruções, além do que é necessário um valor imediato na instrução, com o tamanho de um byte, ou um valor no registrador DX que determina qual porta é a fonte ou destino da transferência. Como qualquer registrador de uso geral pode receber dados de ou para E/S mapeada em memória, esta usa menos instruções e pode ser executada mais rapidamente. A AMD não estendeu as instruções de portas de E/S ao definir a arquitetura x86-64 para suportar as portas 64-bits, e, portanto, as transmissões de dados de 64-bits não podem ser usadas em portas de E/S.

## Limites de memória

E/S mapeada em memória é causa de limitações de memória em gerações antigas de computadores - o limite dos 640 KiB é devido ao fato de o IBM PC colocar a Área Superior da Memória no intervalo de 640-1024 KiB (dos seus 20 bit de endereçamento), enquanto o Limite dos 3 GB se deve ao mapeamento de memória similar nas arquiteturas de 32 bits, no intervalo de 3-4 GB.

## Exemplo

Consideremos um sistema simples construído sobre um microprocessador de 8-bit. Tal CPU possui linhas de endereçamento de 16-bit, permitindo endereçar 64 kibibytes (KiB) de memória. Neste sistema, os primeiros 32 KiB de endereço seriam distribuídos para a memória de acesso aleatório (RAM), 16 K para a memória apenas de leitura (ROM) e o resto para uma variedade de outros dispositivos, tais como timers, contadores, chips de vídeo, dispositivos de som, etc. O hardware do sistema é organizado de tal maneira que os dispositivos dos barramentos de endereço somente responderão a endereços específicos para eles; todos os outros endereços são ignorados. Este é o papel do circuito decodificador de endereços, e é isto que define o mapeamento de memória do sistema.
Dessa forma, o mapa final de memória seria este:
| Dispositivo | Intervalo de endereços (hexadecimal) | Tamanho |
| RAM | 0000 - 7FFF | 32 KiB |
| E/S de uso geral | 8000 - 80FF | 256 bytes |
| Controlador de som | 9000 - 90FF | 256 bytes |
| Controlador de vídeo/RAM do display de mapa de texto | A000 - A7FF | 2 KiB |
| ROM | C000 - FFFF | 16 KiB |
Observe-se que este mapeamento de memória possui lacunas, mas isso é muito comum.
Presumindo que o quarto registrador do controlador de vídeo define a cor de fundo da tela, a CPU pode definir esta cor escrevendo um valor no endereço A003 da memória, usando a instrução padrão de escrita. Usando o mesmo método, recursos gráficos podem ser mostrados na tela ao se escrever valores de caractere em uma área especial da RAM, dentro da área de controle de vídeo. Antes do uso de memória RAM barata, que permitia o uso de deisplays com mapas de bits, este método de células de caracteres era popular para displays (monitores) de vídeo em computadores.

## Tipos básicos de decodificação de endereço

* Exaustivo - 1:1 mapeamento de um endereço único para um registrador de hardware (localização física da memória);
* Parcial - n:1 mapeamento de 'n' endereços únicos para um registrador de hardware. A decodificação parcial permite que um local da memória tenha mais de um endereço, bem como ao programador referenciar um local da memória usando 'n' endereços diferentes. Isto pode também ser feito para simplificar o hardware decodificador quando nem todo o espaço de endereçamento da CPU é necessário. Sinônimos: foldback, mapeamento multiplicado, mapeamento parcial.
* Linear - Linhas de endereço são usadas diretamente, sem nenhuma lógica de decodificação. Isto é feito com dispositivos tais como RAMs ROMs que possuem uma sequência de endereços de entrada, e com chips periféricos que possuem uma sequencia similar de linhas de entrada para endereçamento de um banco de registradores. Este tipo de endereçamento é raramente usado sozinho (somente quando há poucos dispositivos no barramento, pois usar o endereçamento linear puro para mais de um dispositivo normalmente desperdiça muitos espaços de endereço). Em vez disso, combina-se com um dos outros métodos para se selecionar um dispositivo ou grupo de dispositivos destre os quais o endereçamento linear seleciona somente um registrador ou endereço de memória.

## Decodificação incompleta de endereço

Endereços podem ser decodificados completa ou incompletamente por um dispositivo.
* A decodificação completa envolve a checagem de todas a linhas do barramento de endereços, gerando um barramento de dados aberto quando a CPU acessar uma região não mapeada da memória (note-se que mesmo com a decodificação incompleta, regiões parciais decodificadas podem não estar associadas com qualquer dispositivo, deixando o barramento de dados aberto quando essas regiões forem associadas).
* A decodificação incompleta, ou parcial, utiliza uma lógica simples e, frequentemente, mais barata que examina somente as linhas de endereço. Assim, um circuito decodificador simples permitirá a um dispositivo responder a muitos endereços diferentes, criando efetivamente cópias virtuais do dispositivo em diferentes locais do mapeamento. Todas essas cópias referem-se ao mesmo dispositivo real, então não há nenhuma vantagem em particular de se fazer isso, exceto para se simplificar o decodificador (ou, possivelmente, o software que utilizará o dispositivo). Isto também é conhecido como address aliasing, ou renomeação de endereço )Aliasing tem outros sentidos em ciência da computação). Comumente, a decodificação em si é programável, de forma que o sistema pode reconfigurar o seu próprio mapeamento de memória conforme a necessidade, muito embora isto seja uma tendência bastante recente e seja, geralmente, conflitante com a intenção de baratear o hardware.