A que se destina o registro “FS” / “GS”?

102

Então, eu sei quais são os seguintes registros e seus usos:

  • CS = Segmento de Código (usado para IP)

  • DS = segmento de dados (usado para MOV)

  • ES = Segmento de Destino (usado para MOVS, etc.)

  • SS = segmento de pilha (usado para SP)

Mas para que os seguintes registros devem ser usados?

  • FS = "Segmento de arquivo"?

  • GS = ???

Nota: Eu estou não perguntando sobre qualquer sistema operacional particular - Estou perguntando sobre o que eles tinham a intenção de ser usado pelo CPU, se alguma coisa.

user541686
fonte
24
Tanto quanto eu sei, o F e G nestes dois não representam nada. É que havia espaço na CPU (e no conjunto de instruções) para seis registradores de segmento especificáveis ​​pelo usuário, e alguém notou que além do segmento de aderência "S", as letras "C" e "D" (código e dados) estavam em sequência, então "E" era o segmento "extra", e então "F" e "G" simplesmente seguiram.
torek
3
Poderia ter sido, é sempre difícil saber o que se passava na cabeça de outra pessoa, a menos que você estivesse lá na hora (e eu estava na outra costa, longe da equipe de design da Intel).
torek
20
Pense em como poderíamos ter nos divertido com o registro BS: -}
Ira Baxter
5
Sempre usei GS como o "segmento gráfico". :-)
Brian Knoblauch
2
Que tal um "S" egmento "G" geral?
SS Anne de

Respostas:

109

É para isso que foram concebidos e para que são utilizados pelo Windows e Linux.

A intenção original por trás dos registradores de segmento era permitir que um programa acesse muitos segmentos diferentes (grandes) de memória que deveriam ser independentes e parte de um armazenamento virtual persistente. A ideia foi tirada do sistema operacional Multics de 1966 , que tratava os arquivos simplesmente como segmentos de memória endereçáveis. Não BS "Abrir arquivo, gravar registro, fechar arquivo", apenas "Armazenar este valor naquele segmento de dados virtual" com limpeza de página suja.

Nossos sistemas operacionais atuais de 2010 são um grande retrocesso, e é por isso que são chamados de "Eunucos". Você só pode endereçar o único segmento do seu espaço de processo, dando um assim chamado "espaço de endereçamento plano (IMHO opaco)". Os registradores de segmento na máquina x86-32 ainda podem ser usados ​​para registradores de segmentos reais, mas ninguém se importou (Andy Grove, ex-presidente da Intel, teve um famoso ataque público no século passado quando descobriu depois que todos aqueles engenheiros da Intel gastaram energia e seu dinheiro para implementar esse recurso, que ninguém iria usá-lo. Vá, Andy!)

A AMD ao ir para 64 bits decidiu que não se importava se eliminasse o Multics como uma escolha (essa é a interpretação caridosa; a não caridosa é que eles não tinham ideia sobre o Multics) e então desabilitou a capacidade geral de registradores de segmento no modo de 64 bits. Ainda havia a necessidade de threads acessarem o armazenamento local de threads, e cada thread precisava de um ponteiro ... em algum lugar no estado de thread imediatamente acessível (por exemplo, nos registradores) ... para armazenar o armazenamento local de threads. Como o Windows e o Linux usaram FS e GS (obrigado Nick pelo esclarecimento) para este propósito na versão de 32 bits, a AMD decidiu permitir que os registradores de segmento de 64 bits (GS e FS) fossem usados ​​essencialmente apenas para este propósito (acho que você pode faça com que eles apontem para qualquer lugar em seu espaço de processo; não sei se o código do aplicativo pode carregá-los ou não).

Teria sido mais bonito do ponto de vista arquitetônico do IMHO fazer com que o mapa de memória de cada thread tivesse um endereço virtual absoluto (por exemplo, 0-FFF digamos) que fosse seu armazenamento local do thread (nenhum ponteiro de registro [segmento] necessário!); Eu fiz isso em um sistema operacional de 8 bits na década de 1970 e foi extremamente útil, como ter outra grande pilha de registros para trabalhar.

Então, os registradores de segmento agora são como seu apêndice. Eles servem a um propósito residual. Para nossa perda coletiva.

Aqueles que não conhecem a história não estão condenados a repeti-la; eles estão condenados a fazer algo mais estúpido.

Ira Baxter
fonte
10
@supercat: Um esquema mais simples e brilhante que permitiria que eles endereçassem 65536 vezes mais armazenamento seria tratar os registradores de segmento como uma extensão total de 16 bits superior dos 16 bits inferiores, que é essencialmente o que o 286, 386 e Multics fez.
Ira Baxter
3
@IraBaxter: O problema com essa abordagem é que os segmentos do estilo 80286 têm uma sobrecarga suficientemente alta para que acabemos tendo que armazenar muitos objetos em cada segmento e, portanto, armazenar tanto o segmento quanto o deslocamento em cada ponteiro. Em contraste, se alguém estiver disposto a arredondar as alocações de memória para até múltiplos de 16 bytes, a segmentação no estilo 8086 permite que se use o segmento sozinho como meio de identificar um objeto. O arredondamento de alocações para até 16 bytes pode ter sido um pouco enfadonho em 1980, mas representaria uma vitória hoje se reduzisse o tamanho de cada referência de objeto de 8 bytes para quatro.
supercat de
3
Esses registros são usados ​​em sistemas operacionais modernos. Eles são principalmente dedicados a apontar para informações sobre blocos de controle de tarefas, pelo menos nos dois principais sistemas operacionais agora disponíveis para chips x86. E, uma vez que eles não são mais de "uso geral", mesmo para sua intenção original, você não pode usá-los para muito. Melhor fingir em sistemas x86-64 que eles simplesmente não existem até que você precise das informações que eles permitem acessar nos blocos de controle de thread.
Ira Baxter
5
A analogia do apêndice é muito ruim com base em ciência desatualizada; está relacionado ao sistema imunológico, então definitivamente não é "vestigial". Isso prejudica a postagem real. Fora isso, é uma boa resposta.
code_dredd
5
Obrigado pelo tratamento divertido e sem barreiras de memória segmentada vs. plana :) Tendo também escrito código em 6809 (com e sem memória paginada), 6502, z80, 68k e 80 [123]? 86, minha perspectiva é segmentada memória é um show de terror e estou feliz por ter sido jogado na lata de lixo da história. O uso de FS e GS para acesso eficiente aos dados thread_local é uma consequência indesejada feliz de um erro histórico.
Richard Hodges
44

Os registradores FSe GSsão registradores de segmento. Eles não têm um propósito definido pelo processador, mas, em vez disso, são determinados pelo SO que os executa. No Windows de 64 bits, o GSregistro é usado para apontar para estruturas definidas pelo sistema operacional. FSe GSsão comumente usados ​​por kernels do sistema operacional para acessar a memória específica de thread. No Windows, o GSregistro é usado para gerenciar a memória específica do segmento. O kernel do Linux usa GSpara acessar a memória específica da CPU.

cytinus
fonte
1
Eles deveriam ser usados ​​para propósitos definidos pelo sistema operacional ou para facilitar o código que precisa fazer algo *dest++ = lookup[*src++];que, de outra forma, seria um tanto estranho se dest, lookup e src estivessem em três locais não relacionados.
supercat de
8
No Windows FS é de fato para armazenamento específico de thread. Veja o mapa documentado do bloco apontado por FS aqui en.wikipedia.org/wiki/Win32_Thread_Information_Block
Nedko
2
Não é apenas no Windows. GS também é usado para o TLS no OS X. GS também é usado por kernels de 64 bits para controlar as estruturas do sistema durante as mudanças de contexto. O sistema operacional usará SWAPGS para esse efeito.
ET
12

FS é usado para apontar para o bloco de informações de thread (TIB) nos processos do Windows.

um exemplo típico é ( SEH ), que armazena um ponteiro para uma função de retorno de chamada em FS:[0x00].

GS é comumente usado como um ponteiro para um armazenamento local de thread (TLS). e um exemplo que você pode ter visto antes é a proteção canário de pilha (stackguard), no gcc você pode ver algo assim:

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax
zerocool
fonte
2
Na verdade, isso não responde à pergunta. A pergunta afirma : Observação: não estou perguntando sobre nenhum sistema operacional em particular - estou perguntando sobre para que eles deveriam ser usados ​​pela CPU, se houver.
Michael Petch
9
@MichaelPetch ya eu sei que só quero adicionar isso como uma boa informação para aqueles que lêem estas
perguntas
2

De acordo com o Manual da Intel, no modo de 64 bits, esses registros devem ser usados ​​como registros básicos adicionais em alguns cálculos de endereço linear. Retirei isso da seção 3.7.4.1 (pág. 86 no conjunto de 4 volumes). Normalmente, quando a CPU está neste modo, o endereço linear é o mesmo que o endereço efetivo, porque a segmentação geralmente não é usada neste modo.

Portanto, neste espaço de endereço plano, FS e GS desempenham um papel no endereçamento não apenas de dados locais, mas de certas estruturas de dados do sistema operacional (página 2793, seção 3.2.4), portanto, esses registros foram destinados a serem usados ​​pelo sistema operacional, no entanto, esses designers específicos determinar.

Há alguns truques interessantes ao usar substituições nos modos de 32 e 64 bits, mas isso envolve software privilegiado.

Do ponto de vista das "intenções originais", é difícil dizer, a não ser que sejam apenas registros extras. Quando a CPU está no modo de endereço real , é como se o processador estivesse funcionando como um 8086 de alta velocidade e esses registros precisassem ser acessados ​​explicitamente por um programa. Para a verdadeira emulação do 8086, você executaria a CPU no modo virtual-8086 e esses registros não seriam usados.

Robert Houghton
fonte
2

TL; DR;

A que se destina o registro “FS” / “GS”?

Simplesmente para acessar dados além do segmento de dados padrão (DS). Exatamente como o ES.


A longa leitura:

Então, eu sei quais são os seguintes registros e seus usos:

[...]

Bem, quase, mas o DS não é 'algum' segmento de dados, mas o padrão. Todas as operações ocorreram por padrão (* 1). É onde todas as variáveis ​​padrão estão localizadas - essencialmente datae bss. De certa forma, é parte da razão pela qual o código x86 é bastante compacto. Todos os dados essenciais, que são os acessados ​​com mais frequência, (mais o código e a pilha) estão a uma distância abreviada de 16 bits.

O ES é usado para acessar todo o resto (* 2), tudo além dos 64 KiB do DS. Como o texto de um processador de texto, as células de uma planilha ou os dados de imagem de um programa gráfico e assim por diante. Ao contrário do que costumamos presumir, esses dados não são tão acessados, portanto, precisar de um prefixo dói menos do que usar campos de endereço mais longos.

Da mesma forma, é apenas um pequeno aborrecimento que o DS e o ES tenham que ser carregados (e recarregados) ao fazer operações de string - isso pelo menos é compensado por um dos melhores conjuntos de instruções de tratamento de caracteres de seu tempo.

O que realmente dói é quando os dados do usuário excedem 64 KiB e as operações precisam ser iniciadas. Enquanto algumas operações são feitas simplesmente em um único item de dados por vez (pense A=A*2), a maioria requer dois ( A=A*B) ou três itens de dados ( A=B*C). Se esses itens residirem em segmentos diferentes, o ES será recarregado várias vezes por operação, adicionando alguma sobrecarga.

No início, com pequenos programas do mundo de 8 bits (* 3) e conjuntos de dados igualmente pequenos, não era grande coisa, mas logo se tornou um grande gargalo de desempenho - e mais ainda um verdadeiro pé no saco para programadores (e compiladores). Com o 386, a Intel finalmente proporcionou alívio ao adicionar mais dois segmentos, de forma que qualquer operação unária , binária ou ternária em série , com elementos espalhados na memória, poderia ocorrer sem recarregar o ES o tempo todo.

Para programação (pelo menos em montagem) e design do compilador, isso foi um ganho e tanto. Claro, poderia ter havido ainda mais, mas com três o gargalo basicamente havia sumido, então não há necessidade de exagerar.

Em termos de nomenclatura, as letras F / G são simplesmente continuações alfabéticas após E. Pelo menos do ponto de vista do design da CPU, nada está associado.


* 1 - O uso de ES para destino de string é uma exceção, pois são necessários simplesmente dois registradores de segmento. Sem eles não seriam muito úteis - ou sempre precisando de um prefixo de segmento. O que poderia matar um dos recursos surpreendentes, o uso de instruções de string (não repetitivas), resultando em desempenho extremo devido à codificação de byte único.

* 2 - Então, em retrospectiva, 'segmento de tudo o resto' teria sido uma nomenclatura muito melhor do que 'segmento extra'.

* 3 - É sempre importante ter em mente que o 8086 foi criado apenas como uma medida provisória até que o 8800 fosse concluído e destinado principalmente ao mundo embarcado para manter os clientes do 8080/85 a bordo.

Raffzahn
fonte
1
Nossa, obrigado por explicar tudo isso! Isso explica muito e faz muito sentido! +1
user541686