Aprendendo Assembly
Doar para o autor
  • Introdução
  • Conteúdo
  • Como usar este livro
  • A base
    • Noção geral da arquitetura
    • Modos de operação
    • Sintaxe
    • Registradores de propósito geral
    • Endereçamento
    • Pilha
    • Saltos
    • Procedimentos
    • Seções e símbolos
    • Instruções assembly x86
    • Instruções do NASM
    • Pré-processador do NASM
    • Syscall no Linux
    • Olá mundo no Linux
    • Revisão
  • Aprofundando em Assembly
    • Registradores de segmento
    • CALL e RET
    • Position-independent executable
    • Atributos
    • Prefixos
    • Flags do processador
    • Instruções condicionais
    • Programando no MS-DOS
    • Interrupções de software e exceções
    • Procedimentos do BIOS
    • Usando instruções da FPU
    • Entendendo SSE
      • Instruções de movimentação de dados
      • Instruções aritméticas
      • Instruções lógicas e de comparação
      • Instruções com inteiros 128-bit
      • Instruções de conversão
  • Programando junto com C
    • Sintaxe do GAS
    • Convenção de chamada da System V ABI
    • Convenções de chamada no Windows
    • Variáveis em C
    • Funções em C
    • Ambiente hosted
    • Ambiente freestanding
    • Inline Assembly no GCC
    • Instruções intrínsecas
  • Depuração de código
    • Entendendo os depuradores
    • Depurando com o GDB
    • Depurando com o Dosbox
  • Apêndices
    • Código de máquina
      • Formato das instruções
      • Atributos e prefixos
      • Immediate
      • Displacement
      • ModR/M e SIB
      • Opcode
      • Prefixo REX
      • Codificação dos registradores
  • Metadados
    • TO DO
    • Referências
Powered by GitBook
On this page
  • Barramento de endereço
  • Segmentação em IA-16
  • Segmentação em IA-32
  • Segmentação em x86-64

Was this helpful?

Export as PDF
  1. Aprofundando em Assembly

Registradores de segmento

Segmentação da memória RAM.

PreviousAprofundando em AssemblyNextCALL e RET

Last updated 2 years ago

Was this helpful?

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.

Barramento de endereç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 2202^{20}220 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.

Segmentação em IA-16

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:

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

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:

mov [0x100], ax

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.

Podemos especificar um segmento diferente com a seguinte sintaxe do NASM:

; O nome deste recurso é "segment override"
; Ou em PT-BR: Substituição do segmento

mov [es:0x100], ax

; OU alternativamente:

es mov [0x100], ax

A conversão de endereço lógico para endereço físico é feita pelo processador com um cálculo simples:

endereço_físico = (segmento << 4) + deslocamento

O operador << denota um deslocamento de bits para a esquerda, uma operação shift left.

Segmentação em IA-32

Além dos registradores de segmento do IA-16, em IA-32 se ganha mais dois registradores de segmento: FS e GS.

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.

Segmentação em x86-64

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.

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 isso será explicado.

Diferente dos , os registradores de segmento não são expandidos. Permanecem com o tamanho de 16 bits.

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 .

😉
registradores de propósito geral
Atributos
Thread Local Storage