Assembly x86/Registos: diferenças entre revisões

Origem: Wikilivros, livros abertos por um mundo aberto.
[edição não verificada][edição não verificada]
Conteúdo apagado Conteúdo adicionado
Sem resumo de edição
Sem resumo de edição
Linha 33: Linha 33:


Os segmentos são uma idiossincrasia da arquitectura x86, não existindo em praticamente mais nenhuma arquitectura. Sendo assim, os compiladores de linguagens de alto nível geralmente optam por ignorar os segmentos. Por essa razão, os sistemas operativos modernos para x86 (incluindo o Windows e o Linux) tipicamente fazem todos os registos de segmento apontar para o mesmo segmento de 4GB. As excepções a essa regra são geralmente o FS e o GS, que são usados para isolar as secções de dados das diferentes threads de um mesmo processo. As outras arquitecturas utilizam registos especiais chamados ''registos de thread'' para esse efeito, os quais não existem no x86.
Os segmentos são uma idiossincrasia da arquitectura x86, não existindo em praticamente mais nenhuma arquitectura. Sendo assim, os compiladores de linguagens de alto nível geralmente optam por ignorar os segmentos. Por essa razão, os sistemas operativos modernos para x86 (incluindo o Windows e o Linux) tipicamente fazem todos os registos de segmento apontar para o mesmo segmento de 4GB. As excepções a essa regra são geralmente o FS e o GS, que são usados para isolar as secções de dados das diferentes threads de um mesmo processo. As outras arquitecturas utilizam registos especiais chamados ''registos de thread'' para esse efeito, os quais não existem no x86.

Em Modo Longo, a base e o tamanho dos segmentos não depende dos valores contidos nos registos CS, DS, ES ou SS. Contudo, os registos continuam a existir e o seu valor a ter significado.


== Registo das flags ==
== Registo das flags ==

Revisão das 01h52min de 30 de setembro de 2007

A arquitectura x86 tem 8 registos de uso geral (General-Purpose Registers - GPR), 6 registos de segmento, 1 registo de flags e um Apontador de Execução (Instruction Pointer). (FIXME: no AMD64/EM64T há mais de 8 GPRs)

Wikipedia
Wikipedia
A Wikipédia tem mais sobre este assunto:
Registrador (informática)

Registos de Uso Geral

Os 8 GPRs, ou Registos de Uso Geral, são os seguintes (por ordem de introdução na pilha ao executar a instrução PUSHAD):

  • EAX - Acumulador. Usado em operações aritméticas.
  • ECX - Contador. Usado em loops.
  • EDX - Registo de Dados. Usado em operações de entrada/saída e em multiplicações e divisões. É também uma extensão do Acumulador.
  • EBX - Base. Usado para apontar para dados no segmento DS.
  • ESP - Apontador da Pilha (Stack Pointer). Aponta para o topo da pilha (endereço mais baixo dos elementos da pilha).
  • EBP - Apontador da base do frame. Usado para aceder a argumentos de procedimentos passados pela pilha.
  • ESI - Índice da fonte de dados a copiar (Source Index). Aponta para dados a copiar para DS:EDI.
  • EDI - Índice do destino de dados a copiar (Destination Index). Aponta para o destino dos dados a copiar de DS:ESI.

Estes 8 registos têm 32 bits cada um e dizem-se Extendidos. Os 16 bits de ordem mais baixa de cada um dos registos podem ser acedidos atraves das versões não extendidas destes. As versões de 16 bits têm os mesmo nomes que as de 32 bits, com excepção de a letra E ser retirada (ex: EAX → AX). As versões extendidas dos registos não existem em gerações anteriores à 80386 ― a primeira geração de processadores 32 bits da arquitectura x86.

As versões não extendidas dos quatro primeiros GPRs dividem-se ainda em dois grupos de 8 bits cada um. O octeto (byte) de ordem mais alta é acedido trocando o X por um H (ex: AX → AH), e o octeto de ordem mais baixa trocando o X por um L (ex: AX → AL).

Nota: Nos processadores da arquitectura AMD64/EM64T, os GPRs têm 64 bits e pode aceder-se à totalidade dos bits através dos nomes RAX, RCX, RDX, etc. Adicionalmente, existem ainda mais oito GPRs, de 64 bits cada um. Isto só é válido se o processador estiver em Modo Longo.

Registos de segmento

Há 6 registos de segmento.

  • CS - Segmento do Código
  • DS - Segmento de Dados
  • ES - Segmento com dados extra
  • FS - Segmento com mais dados
  • GS - Segmento com ainda mais dados
  • SS - Segmento da Pilha (Stack)

Os segmentos são uma idiossincrasia da arquitectura x86, não existindo em praticamente mais nenhuma arquitectura. Sendo assim, os compiladores de linguagens de alto nível geralmente optam por ignorar os segmentos. Por essa razão, os sistemas operativos modernos para x86 (incluindo o Windows e o Linux) tipicamente fazem todos os registos de segmento apontar para o mesmo segmento de 4GB. As excepções a essa regra são geralmente o FS e o GS, que são usados para isolar as secções de dados das diferentes threads de um mesmo processo. As outras arquitecturas utilizam registos especiais chamados registos de thread para esse efeito, os quais não existem no x86.

Registo das flags

O registo das flags é chamado EFLAGS (Extended Flags) nas arquitecturas de 32 bits, sendo a sua versão de 16 bits chamada simplesmente FLAGS. Tal como com os GPRs, os processadores x86 anteriores ao i386 não possuem a versão de 32 bits. Nos processadores de 64 bits, este registo também tem 64 bits e chama-se RFLAGS.

No esquema abaixo, os 16 bits menos significativos aparecem a cinza, enquanto que os bits a azul apenas existem em processadores da geração do i386 ou posteriores.

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
0 0 0 0 0 0 0 0 0 0 ID VIP VIF AC VM RF
 
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF

Ao carregar um novo valor no EFLAGS, os bits que aparecem no esquema como 1 ou 0 devem ser carregados como tal, de modo a preservar a compatibilidade do software com gerações futuras da arquitectura.

Note-se que utilizar um método convencional para aceder a este registo produz um erro do montador (assembler), uma vez que o x86 não fornece nenhuma forma de aceder directamente ao registo das flags. Para modificar ou ler o eflags é necessário utilizar a instrução pushf (16 bits) ou pushaf (32 bits).

O Apontador de Execução

O Apontador de execução, ou Instruction Pointer (genericamente conhecido na ciência da computação por Program Counter), do x86 é um registo interno que aponta para a próxima instrução a ser executada.

O seu nome é EIP e a parte que contem os 16 bits menos significativos denomina-se IP. Tal como no caso do registo das flags, não é possível utilizar um método convencional para aceder ao Apontador de Execução. Ele tem de ser introduzido no stack por meio de uma instrução call ou semelhante.