Segmentação da memória RAM.
Na arquitetura x86 o acesso a memória RAM é comumente dividido em segmentos. Um segmento de memória nada mais é que um pedaço da memória RAM que o programador usa dando algum sentido a ele. Por exemplo, podemos usar um segmento só para armazenar variáveis. E usar outro para armazenar o código executado pelo processador.
Rodando sob um sistema operacional a segmentação da memória é totalmente controlada pelo kernel. Ou seja, não tente fazer o que você não tem permissão.
O barramento de endereço (address bus) é um socket do processador que serve para se comunicar com a memória principal (memória RAM), ele indica o endereço físico na memória principal de onde o processador quer ler ou escrever dados. Basicamente a largura desse barramento indica quanta memória o processador consegue endereçar já que ele indica o endereço físico da memória que se deseja acessar.
Em IA-16 o barramento tem o tamanho padrão de 20 bits. Calculando temos o número de bytes endereçáveis que são exatamente 1 MiB de memória que pode ser endereçada. É da largura do barramento de endereço que surge a limitação de tamanho da memória RAM.
Em IA-32 e x86-64 o barramento de endereço tem a largura de 32 e 48 bits respectivamente.
Em IA-16 a segmentação é bem simplista e o código trabalha basicamente com 4 segmentos simultaneamente. Esses segmentos são definidos simplesmente alterando o registrador de segmento equivalente, cujo eles são:
Cada um desses registradores tem 16 bits de tamanho.
Quando acessamos um endereço na memória estamos usando um endereço lógico que é a junção de um segmento (segment) e um deslocamento (offset), seguindo o formato:
segment:offset
O tamanho do valor de offset é o mesmo tamanho do registrador IP/EIP/RIP.
Veja por exemplo a instrução:
O endereçamento definido pelos colchetes é na verdade o offset que, juntamente com o registrador DS, se obtém o endereço físico. Ou seja o endereço lógico é DS:0x100
.
O segmento padrão (nesse caso DS) usado para acessar o endereço depende de qual registrador e instrução está sendo utilizado. No tópico Atributos isso será explicado.
Podemos especificar um segmento diferente com a seguinte sintaxe do NASM:
A conversão de endereço lógico para endereço físico é feita pelo processador com um cálculo simples:
O operador <<
denota um deslocamento de bits para a esquerda, uma operação shift left.
Além dos registradores de segmento do IA-16, em IA-32 se ganha mais dois registradores de segmento: FS
e GS
.
Diferente dos registradores de propósito geral, os registradores de segmento não são expandidos. Permanecem com o tamanho de 16 bits.
Em protected mode os registradores de segmento não são usados para gerar um endereço lógico junto com o offset, ao invés disso, serve de seletor identificando o segmento por um índice em uma tabela que lista os segmentos.
Em x86-64 não é mais usado esse esquema de segmentação de memória. CS, DS, ES e SS são tratados como se o endereço base fosse zero independentemente do valor nesses registradores.
Já os registradores FS e GS são exceções e ainda podem ser usados pelo sistema operacional para endereçamento de estruturas especiais na memória. Como por exemplo no Linux, em x86-64, FS é usado para apontar para a Thread Local Storage.
Registrador
Nome
CS
Code Segment / Segmento de código
DS
Data Segment / Segmento de dado
ES
Extra Segment / Segmento extra
SS
Stack Segment / Segmento da pilha