¿Para qué está destinado el registro “FS” / “GS”?

102

Entonces sé cuáles se supone que son los siguientes registros y sus usos:

  • CS = Segmento de código (utilizado para IP)

  • DS = segmento de datos (utilizado para MOV)

  • ES = Segmento de destino (utilizado para MOVS, etc.)

  • SS = Segmento de pila (usado para SP)

Pero, ¿para qué están destinados los siguientes registros?

  • FS = "Segmento de archivo"?

  • GS = ???

Nota: Estoy no preguntar sobre cualquier sistema operativo en particular - Me estoy preguntando por lo que estaban destinados a ser utilizados por la CPU, en todo caso.

usuario541686
fuente
24
Hasta donde yo sé, la F y la G en estos dos no representan nada. Es solo que había espacio en la CPU (y en el conjunto de instrucciones) para seis registros de segmento especificables por el usuario, y alguien notó que además del segmento de tachuela "S", las letras "C" y "D" (código y datos) estaban en secuencia, por lo que "E" era el segmento "extra", y luego "F" y "G" simplemente seguían.
torek
3
Podría haber sido, siempre es difícil saber qué estaba pasando en la cabeza de otra persona a menos que estuvieras allí en ese momento (y yo estaba en la otra costa, ni cerca del equipo de diseño de Intel).
torek
20
Piense en lo mucho que podríamos habernos divertido con el registro BS: -}
Ira Baxter
5
Siempre usé GS como el "segmento de gráficos". :-)
Brian Knoblauch
2
¿Qué tal el ejemplo "G" eneral "S"?
SS Anne

Respuestas:

109

Hay para qué fueron diseñados, y para qué los utilizan Windows y Linux.

La intención original detrás de los registros de segmento era permitir que un programa acceda a muchos segmentos diferentes (grandes) de memoria que estaban destinados a ser independientes y formar parte de una tienda virtual persistente. La idea se tomó del sistema operativo Multics de 1966 , que trataba los archivos como simples segmentos de memoria direccionables. No BS "Abrir archivo, escribir registro, cerrar archivo", simplemente "Almacenar este valor en ese segmento de datos virtuales" con eliminación de páginas sucias.

Nuestros sistemas operativos actuales de 2010 son un paso gigantesco hacia atrás, por eso se les llama "Eunucos". Solo puede abordar el segmento único de su espacio de proceso, lo que proporciona un "espacio de direcciones plano (en mi humilde opinión)". Los registros de segmento en la máquina x86-32 aún se pueden usar para registros de segmento reales, pero nadie se ha molestado (Andy Grove, ex presidente de Intel, tuvo un ataque público bastante famoso el siglo pasado cuando se dio cuenta después de que todos esos ingenieros de Intel gastaron energía y su dinero para implementar esta función, que nadie iba a usarla. ¡Ve, Andy!)

AMD, al pasar a 64 bits, decidió que no les importaba si eliminaban Multics como opción (esa es la interpretación caritativa; la poco caritativa es que no tenían ni idea de Multics) y, por lo tanto, deshabilitó la capacidad general de los registros de segmento en el modo de 64 bits. Todavía existía la necesidad de que los subprocesos accedan a la tienda local de subprocesos, y cada subproceso necesitaba un puntero ... en algún lugar del estado de subproceso inmediatamente accesible (por ejemplo, en los registros) ... para el almacén local de subprocesos. Dado que Windows y Linux usaron FS y GS (gracias Nick por la aclaración) para este propósito en la versión de 32 bits, AMD decidió permitir que los registros de segmento de 64 bits (GS y FS) se usaran esencialmente solo para este propósito (creo que puede hágalos apuntar a cualquier lugar de su espacio de proceso; no sé si el código de la aplicación puede cargarlos o no).

Hubiera sido arquitectónicamente más bonito en mi humilde opinión hacer que el mapa de memoria de cada hilo tuviera una dirección virtual absoluta (por ejemplo, 0-FFF digamos) que era su almacenamiento local del hilo (¡no se necesita un puntero de registro [segmento]!); Hice esto en un sistema operativo de 8 bits en la década de 1970 y fue extremadamente útil, como tener otra gran pila de registros para trabajar.

Entonces, los registros de segmento ahora son como su apéndice. Tienen un propósito vestigial. Para nuestra pérdida colectiva.

Los que no conocen la historia no están condenados a repetirla; están condenados a hacer algo más tonto.

Ira Baxter
fuente
10
@supercat: Un esquema más simple y brillante que les habría permitido abordar 65536 veces más almacenamiento, habría sido tratar los registros de segmento como una extensión superior completa de 16 bits de los 16 bits inferiores, que es en esencia lo que 286, 386 y Multics lo hizo.
Ira Baxter
3
@IraBaxter: El problema con ese enfoque es que los segmentos de estilo 80286 tienen una sobrecarga lo suficientemente alta como para que uno termine teniendo que almacenar muchos objetos en cada segmento y, por lo tanto, almacenar tanto el segmento como el desplazamiento en cada puntero. Por el contrario, si uno está dispuesto a redondear las asignaciones de memoria hasta múltiplos de 16 bytes, la segmentación al estilo 8086 le permite usar el segmento solo como un medio para identificar un objeto. Redondear las asignaciones hasta 16 bytes podría haber sido un poco molesto en 1980, pero representaría una victoria hoy si redujera el tamaño de cada referencia de objeto de 8 bytes a cuatro.
supercat
3
Estos registros se utilizan en sistemas operativos modernos. En su mayoría, están dedicados a señalar información sobre bloques de control de tareas, al menos en los dos principales sistemas operativos ahora disponibles para chips x86. Y, dado que ya no son de "propósito general" incluso para su intención original, no puede usarlos para mucho. Es mejor pretender en los sistemas x86-64 que simplemente no existen hasta que necesite la información a la que le permiten acceder en los bloques de control de subprocesos.
Ira Baxter
5
La analogía del apéndice es realmente mala basada en ciencia obsoleta; está relacionado con el sistema inmunológico, por lo que definitivamente no es "vestigial". Le resta valor a la publicación real. Aparte de eso, es una buena respuesta.
code_dredd
5
Gracias por el tratamiento divertido y sin restricciones de la memoria segmentada frente a la plana :) Habiendo escrito también código en 6809 (con y sin memoria paginada), 6502, z80, 68k y 80 [123]? 86, mi perspectiva es así de segmentada La memoria es un espectáculo de terror y me alegro de que haya sido enviado al basurero de la historia. El uso de FS y GS para un acceso eficiente a los datos de thread_local es una feliz consecuencia involuntaria de un error histórico.
Richard Hodges
44

Los registros FSy GSson registros de segmento. No tienen un propósito definido por el procesador, sino que el sistema operativo que los ejecuta les da un propósito. En Windows de 64 bits, el GSregistro se utiliza para señalar las estructuras definidas por el sistema operativo. FSy GSson comúnmente utilizados por los núcleos del sistema operativo para acceder a la memoria específica de subprocesos. En Windows, el GSregistro se usa para administrar la memoria específica de subprocesos. El kernel de Linux utiliza GSpara acceder a la memoria específica de la CPU.

cytinus
fuente
1
¿Estaban destinados a ser usados ​​para propósitos definidos por el sistema operativo, o para facilitar el código que necesita hacer algo como *dest++ = lookup[*src++];lo que de otra manera sería bastante incómodo si dest, lookup y src estuvieran en tres ubicaciones no relacionadas?
supercat
8
En Windows, FS es de hecho para almacenamiento específico de subprocesos. Vea el mapa documentado del bloque señalado por FS aquí en.wikipedia.org/wiki/Win32_Thread_Information_Block
Nedko
2
No es solo en Windows. GS también se usa para TLS en OS X. GS también lo usan los núcleos de 64 bits para realizar un seguimiento de las estructuras del sistema durante los cambios de contexto. El sistema operativo utilizará SWAPGS a tal efecto.
ET
12

FS se utiliza para señalar el bloque de información de subprocesos (TIB) en los procesos de Windows.

un ejemplo típico es ( SEH ) que almacena un puntero a una función de devolución de llamada en FS:[0x00].

GS se usa comúnmente como un puntero a un almacenamiento local de subprocesos (TLS). y un ejemplo que puede haber visto antes es la protección canary de pila (stackguard), en gcc puede ver algo como esto:

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax
cero frío
fuente
2
En realidad, esto no responde a la pregunta. La pregunta dice : Nota: No estoy preguntando sobre ningún sistema operativo en particular, estoy preguntando para qué estaban destinados a ser utilizados por la CPU, en todo caso.
Michael Petch
9
@MichaelPetch ya sé que solo quiero agregar esto como buena información para aquellos que leen esta q / s en SO
zerocool
2

Según el Manual de Intel, en el modo de 64 bits, estos registros están pensados ​​para usarse como registros base adicionales en algunos cálculos de direcciones lineales. Saqué esto de la sección 3.7.4.1 (p. 86 en el conjunto de 4 volúmenes). Por lo general, cuando la CPU está en este modo, la dirección lineal es la misma que la dirección efectiva, porque la segmentación a menudo no se usa en este modo.

Entonces, en este espacio de direcciones plano, FS y GS juegan un papel en el direccionamiento no solo de datos locales, sino de ciertas estructuras de datos del sistema operativo (pg 2793, sección 3.2.4), por lo que estos registros estaban destinados a ser utilizados por el sistema operativo, sin embargo, esos diseñadores particulares determinar.

Hay algunos trucos interesantes al usar anulaciones en los modos de 32 y 64 bits, pero esto implica software privilegiado.

Desde la perspectiva de las "intenciones originales", es difícil decir que son solo registros adicionales. Cuando la CPU está en modo de dirección real , es como si el procesador se estuviera ejecutando como un 8086 de alta velocidad y estos registros deben ser accedidos explícitamente por un programa. Por el bien de la verdadera emulación 8086, ejecutaría la CPU en modo virtual-8086 y estos registros no se utilizarían.

Robert Houghton
fuente
2

TL; DR;

¿Para qué está destinado el registro “FS” / “GS”?

Simplemente para acceder a datos más allá del segmento de datos predeterminado (DS). Exactamente como ES.


La lectura larga:

Entonces sé cuáles se supone que son los siguientes registros y sus usos:

[...]

Bueno, casi, pero DS no es "algún" segmento de datos, sino el predeterminado. Todas las operaciones se realizaron de forma predeterminada (* 1). Aquí es donde se encuentran todas las variables predeterminadas, esencialmente datay bss. De alguna manera, es parte de la razón por la que el código x86 es bastante compacto. Todos los datos esenciales, que es lo que se accede con mayor frecuencia (más el código y la pila) se encuentran a una distancia abreviada de 16 bits.

ES se usa para acceder a todo lo demás (* 2), todo más allá de los 64 KiB de DS. Como el texto de un procesador de texto, las celdas de una hoja de cálculo o los datos de imagen de un programa de gráficos, etc. A diferencia de lo que se supone a menudo, no se accede tanto a estos datos, por lo que necesitar un prefijo duele menos que usar campos de dirección más largos.

Similar, es solo una molestia menor que DS y ES puedan tener que cargarse (y recargarse) al realizar operaciones de cadena; esto al menos se compensa con uno de los mejores conjuntos de instrucciones de manejo de caracteres de su tiempo.

Lo que realmente duele es cuando los datos del usuario superan los 64 KiB y las operaciones deben comenzar. Si bien algunas operaciones se realizan simplemente en un solo elemento de datos a la vez (piense A=A*2), la mayoría requiere dos ( A=A*B) o tres elementos de datos ( A=B*C). Si estos elementos residen en diferentes segmentos, ES se recargará varias veces por operación, agregando bastante sobrecarga.

Al principio, con programas pequeños del mundo de 8 bits (* 3) y conjuntos de datos igualmente pequeños, no fue un gran problema, pero pronto se convirtió en un cuello de botella de rendimiento importante, y más aún en un verdadero dolor de cabeza para programadores (y compiladores). Con el 386 Intel finalmente entregó alivio al agregar dos segmentos más, por lo que cualquier operación unaria , binaria o ternaria en serie, con elementos esparcidos en la memoria, podría tener lugar sin tener que recargar ES todo el tiempo.

Para la programación (al menos en ensamblador) y el diseño del compilador, esto fue una gran ganancia. Por supuesto, podría haber habido aún más, pero con tres el cuello de la botella básicamente se había ido, así que no hay necesidad de exagerar.

Al nombrar las letras F / G son simplemente continuaciones alfabéticas después de E. Al menos desde el punto de vista del diseño de la CPU, no hay nada asociado.


* 1 - El uso de ES para el destino de cadenas es una excepción, ya que simplemente se necesitan dos registros de segmento. Sin ellos, no serían muy útiles, o necesitarían siempre un prefijo de segmento. Lo que podría matar una de las características sorprendentes, el uso de instrucciones de cadena (no repetitivas) que resultan en un rendimiento extremo debido a su codificación de un solo byte.

* 2 - Entonces, en retrospectiva, 'Segmento de todo lo demás' habría sido un nombre mucho mejor que 'Segmento adicional'.

* 3 - Siempre es importante tener en cuenta que el 8086 solo se pensó como una medida provisional hasta que el 8800 se terminó y estaba destinado principalmente al mundo integrado para mantener a los clientes del 8080/85 a bordo.

Raffzahn
fuente
1
¡Vaya, gracias por explicar todo esto! ¡Esto explica mucho y tiene mucho sentido! +1
user541686