Do czego służy rejestr „FS” / „GS”?


103

Wiem więc, jakie mają być następujące rejestry i ich zastosowania:

  • CS = Segment kodu (używany dla IP)

  • DS = Segment danych (używany dla MOV)

  • ES = Segment docelowy (używany w przypadku MOVS itp.)

  • SS = Segment stosu (używany dla SP)

Ale do czego służą poniższe rejestry?

  • FS = "Segment pliku"?

  • GS = ???

Uwaga: nie pytam o żaden konkretny system operacyjny - pytam o to, do czego miały być używane przez procesor, jeśli w ogóle.


24
O ile wiem, F i G w tych dwóch nic nie znaczą. Chodzi o to, że w CPU (i zestawie instrukcji) było miejsce na sześć rejestrów segmentów określanych przez użytkownika i ktoś zauważył, że oprócz segmentu „S”, litery „C” i „D” (kod i dane) były w kolejności, więc „E” było „dodatkowym” segmentem, a „F” i „G” po prostu następowały.
torek

3
Mogło być, zawsze trudno jest wiedzieć, co się dzieje w czyjejś głowie, chyba że byłeś tam w tym czasie (a ja byłem na drugim wybrzeżu, nigdzie w pobliżu zespołu projektowego Intela).
torek

20
Pomyśl tylko, ile radości mogliśmy mieć z rejestrem BS: -}
Ira Baxter

5
Zawsze używałem GS jako „segmentu grafiki”. :-)
Brian Knoblauch

2
A co z „G” eneralnym „S” egmentem?
SS Anne

Odpowiedzi:


110

Jest do czego były przeznaczone i do czego są używane w systemach Windows i Linux.

Pierwotnym zamiarem stojącym za rejestrami segmentowymi było umożliwienie programowi dostępu do wielu różnych (dużych) segmentów pamięci, które miały być niezależne i stanowić część trwałego magazynu wirtualnego. Pomysł zaczerpnięto z systemu operacyjnego Multics z 1966 roku , w którym pliki były po prostu adresowalnymi segmentami pamięci. Brak BS „Otwórz plik, zapisz rekord, zamknij plik”, po prostu „Zapisz tę wartość w tym wirtualnym segmencie danych” z brudnym opróżnianiem strony.

Nasze obecne systemy operacyjne na rok 2010 to ogromny krok wstecz, dlatego nazywają się „Eunuchs”. Można tylko zająć twojego pojedynczego segmentu kosmicznego procesowego, dając tak zwany „płaski (IMHO matowa) przestrzeni adresowej”. Rejestry segmentowe na maszynie x86-32 mogą być nadal używane do prawdziwych rejestrów segmentowych, ale nikt się tym nie przejmował (Andy Grove, były prezes Intela, miał dość słynne publiczne dopasowanie w zeszłym wieku, kiedy zorientował się, że wszyscy inżynierowie Intela zużyli energię i jego pieniądze na wdrożenie tej funkcji, że nikt nie będzie z niej korzystał. Idź, Andy!)

AMD, idąc na 64 bity, zdecydowało, że nie obchodzi ich, czy wyeliminują Multics jako wybór (taka jest charytatywna interpretacja; nieżyczliwa jest to, że nie mają pojęcia o Multics), a więc wyłączyli ogólną możliwość rejestrów segmentowych w trybie 64-bitowym. Wciąż istniała potrzeba wątków, aby uzyskać dostęp do lokalnego magazynu wątków, a każdy wątek potrzebował wskaźnika ... gdzieś w natychmiast dostępnym stanie wątku (np. W rejestrach) ... do wątku w lokalnym magazynie. Ponieważ zarówno Windows, jak i Linux używały FS i GS (dzięki Nickowi za wyjaśnienie) do tego celu w wersji 32-bitowej, AMD zdecydowało się pozwolić, aby 64-bitowe rejestry segmentowe (GS i FS) były używane zasadniczo tylko do tego celu (myślę, że można ustaw je w dowolnym miejscu w przestrzeni procesu; nie wiem, czy kod aplikacji może je załadować, czy nie).

Byłoby ładniejszym architektonicznie IMHO, gdyby mapa pamięci każdego wątku miała bezwzględny adres wirtualny (np. 0-FFF powiedz), który był jego lokalną pamięcią wątku (nie jest potrzebny wskaźnik rejestru [segment]!); Zrobiłem to w 8-bitowym systemie operacyjnym w latach siedemdziesiątych i było to niezwykle przydatne, jak posiadanie kolejnego dużego stosu rejestrów do pracy.

Zatem rejestry segmentowe są teraz trochę podobne do twojego dodatku. Służą szczątkowemu celowi. Za naszą zbiorową stratę.

Ci, którzy nie znają historii, nie są skazani na jej powtarzanie; są skazani na zrobienie czegoś głupszego.


11
@supercat: Prostszy, bardziej genialny schemat, który pozwoliłby im zaadresować 65536 razy więcej pamięci, traktowałby rejestry segmentu jako pełne górne 16-bitowe rozszerzenie dolnych 16 bitów, co jest w istocie tym, co 286, 386 a Multics tak.
Ira Baxter

4
@IraBaxter: Problem z tym podejściem polega na tym, że segmenty w stylu 80286 mają wystarczająco wysokie narzuty, aby jeden z nich musiał przechowywać wiele obiektów w każdym segmencie, a zatem przechowywać zarówno segment, jak i przesunięcie na każdym wskaźniku. W przeciwieństwie do tego, jeśli ktoś chce zaokrąglić alokacje pamięci do wielokrotności 16 bajtów, segmentacja w stylu 8086 pozwala na użycie samego segmentu jako środka do identyfikacji obiektu. Zaokrąglanie alokacji do 16 bajtów mogło być nieco uciążliwe w 1980 r., Ale dziś oznaczałoby zwycięstwo, gdyby zmniejszyło rozmiar każdego odwołania do obiektu z 8 bajtów do czterech.
supercat

3
Rejestry te używane w nowoczesnych systemach operacyjnych. Są one głównie przeznaczone do wskazywania informacji o blokach kontroli zadań, przynajmniej w dwóch głównych systemach operacyjnych dostępnych obecnie dla układów x86. A ponieważ nie mają już „ogólnego przeznaczenia”, nawet w ich pierwotnym celu, nie można ich używać zbyt często. Lepiej udawać w systemach x86-64, że po prostu nie istnieją, dopóki nie będziesz potrzebować informacji, do których dają ci dostęp w blokach kontroli wątków.
Ira Baxter

5
Analogia wyrostka robaczkowego jest naprawdę zła w oparciu o przestarzałą wiedzę; jest związana z układem odpornościowym, więc zdecydowanie nie jest „szczątkowa”. To umniejsza faktyczny post. Poza tym to dobra odpowiedź.
code_dredd

5
Dzięki za zabawne, bez ograniczeń traktowanie pamięci segmentowanej a płaskiej :) Po napisaniu kodu na 6809 (z pamięcią stronicowaną i bez), 6502, z80, 68k i 80 [123]? 86, moja perspektywa jest taka segmentowana Pamięć to horror i cieszę się, że trafiła na śmietnik historii. Użycie FS i GS do wydajnego dostępu do danych thread_local jest szczęśliwą niezamierzoną konsekwencją historycznego błędu.
Richard Hodges

44

Rejestry FSi GSsą rejestrami segmentowymi. Nie mają celu zdefiniowanego przez procesor, ale zamiast tego są nadawane przez system operacyjny, który je uruchamia. W 64-bitowym systemie Windows GSrejestr służy do wskazywania struktur zdefiniowanych w systemie operacyjnym. FSi GSsą powszechnie używane przez jądra systemu operacyjnego do uzyskiwania dostępu do pamięci specyficznej dla wątków. W systemie Windows GSrejestr służy do zarządzania pamięcią specyficzną dla wątków. Jądro Linuksa używa GSdo uzyskania dostępu do pamięci specyficznej dla procesora.


1
Czy były przeznaczone do użycia do celów zdefiniowanych przez system operacyjny, czy do ułatwienia wykonywania kodu, który w *dest++ = lookup[*src++];innym przypadku byłby raczej niezręczny, gdyby dest, lookup i src znajdowały się w trzech niepowiązanych lokalizacjach.
supercat

8
W systemie Windows FS jest rzeczywiście przeznaczony do magazynowania określonego wątku. Zobacz udokumentowaną mapę bloku wskazanego przez FS tutaj en.wikipedia.org/wiki/Win32_Thread_Information_Block
Nedko

2
Nie dotyczy tylko systemu Windows. GS jest również używany do TLS w systemie OS X. GS jest również używany przez jądra 64-bitowe do śledzenia struktur systemu podczas przełączania kontekstu. System operacyjny użyje w tym celu SWAPGS.
ET

13

FS służy do wskazywania bloku informacji o wątku (TIB) w procesach systemu Windows.

jednym typowym przykładem jest ( SEH ), który przechowuje wskaźnik do funkcji zwrotnej w FS:[0x00].

GS jest powszechnie używany jako wskaźnik do lokalnego magazynu wątków (TLS). a jednym przykładem, który mogłeś zobaczyć wcześniej, jest ochrona stosu (stackguard), w gcc możesz zobaczyć coś takiego:

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax

2
To właściwie nie odpowiada na pytanie. Pytanie brzmi : Uwaga: nie pytam o żaden konkretny system operacyjny - pytam o to, do czego miały być używane przez procesor, jeśli w ogóle.
Michael Petch,

10
@MichaelPetch ya, wiem, że chcę tylko dodać to jako dobrą informację dla tych, którzy czytają te
pytania

3

Zgodnie z podręcznikiem Intela, w trybie 64-bitowym rejestry te mają być używane jako dodatkowe rejestry bazowe w niektórych obliczeniach adresu liniowego. Wyciągnąłem to z sekcji 3.7.4.1 (str. 86 w zestawie 4 tomów). Zwykle, gdy procesor jest w tym trybie, adres liniowy jest taki sam jak adres efektywny, ponieważ segmentacja często nie jest używana w tym trybie.

Tak więc w tej płaskiej przestrzeni adresowej FS i GS odgrywają rolę w adresowaniu nie tylko danych lokalnych, ale niektórych struktur danych systemu operacyjnego (str. 2793, sekcja 3.2.4), zatem te rejestry były przeznaczone do wykorzystania przez system operacyjny, jednak ci konkretni projektanci określać.

Istnieje kilka interesujących sztuczek podczas używania nadpisań w obu trybach 32 i 64-bitowych, ale dotyczy to uprzywilejowanego oprogramowania.

Z punktu widzenia „oryginalnych intencji”, trudno powiedzieć inaczej niż są to tylko dodatkowe rejestry. Kiedy procesor jest w trybie adresu rzeczywistego , jest to tak, jakby procesor działał jako szybki 8086 i te rejestry muszą być jawnie dostępne przez program. Ze względu na prawdziwą emulację 8086 procesor uruchomiłbyś w trybie virtual-8086 i te rejestry nie byłyby używane.


2

TL; DR;

Do czego służy rejestr „FS” / „GS”?

Po prostu dostęp do danych poza domyślnym segmentem danych (DS). Dokładnie jak ES.


Długa lektura:

Wiem więc, jakie mają być następujące rejestry i ich zastosowania:

[…]

Cóż, prawie, ale DS nie jest „jakimś” segmentem danych, ale domyślnym. Czy wszystkie operacje odbywały się domyślnie (* 1). To jest miejsce, w którym znajdują się wszystkie domyślne zmienne - zasadniczo datai bss. W pewnym sensie jest to jeden z powodów, dla których kod x86 jest raczej zwarty. Wszystkie istotne dane, które są najczęściej używane (plus kod i stos), znajdują się w odległości 16-bitowej.

ES jest używany do uzyskiwania dostępu do wszystkiego innego (* 2), wszystkiego poza 64 KiB DS. Podobnie jak tekst w edytorze tekstu, komórki arkusza kalkulacyjnego lub dane obrazu w programie graficznym i tak dalej. W przeciwieństwie do często zakładanych danych, dostęp do tych danych nie jest tak duży, więc potrzeba prefiksu jest mniej bolesna niż używanie dłuższych pól adresowych.

Podobnie jest tylko niewielką irytacją, że DS i ES mogą być ładowane (i ponownie ładowane) podczas wykonywania operacji na łańcuchach - jest to przynajmniej kompensowane przez jeden z najlepszych zestawów instrukcji obsługi znaków w tamtych czasach.

To, co naprawdę boli, to sytuacja, gdy dane użytkownika przekraczają 64 KB i trzeba rozpocząć operacje. Podczas gdy niektóre operacje są po prostu wykonywane na pojedynczym elemencie danych na raz (pomyśl A=A*2), większość wymaga dwóch ( A=A*B) lub trzech elementów danych ( A=B*C). Jeśli te elementy znajdują się w różnych segmentach, ES będzie przeładowywana kilka razy na operację, co zwiększy nieco narzut.

Na początku, z małymi programami ze świata 8-bitowego (* 3) i równie małymi zestawami danych, nie było to nic wielkiego, ale wkrótce stało się to wąskim gardłem o dużej wydajności - a tym bardziej prawdziwym bólem w dupie dla programiści (i kompilatorzy). Dzięki procesorowi 386 Intel w końcu zapewnił ulgę, dodając dwa kolejne segmenty, więc każda szeregowa operacja jednoargumentowa , binarna lub trójskładnikowa z elementami rozłożonymi w pamięci mogła odbywać się bez ciągłego przeładowywania ES.

W przypadku programowania (przynajmniej w asemblerze) i projektowania kompilatorów było to spore korzyści. Oczywiście mogło być ich jeszcze więcej, ale przy trzech praktycznie nie było szyjki butelki, więc nie trzeba przesadzać.

Mądre nazewnictwo litery F / G są po prostu kontynuacją alfabetyczną po E. Przynajmniej od punktu projektowania procesora nic nie jest ze sobą powiązane.


* 1 - Wyjątek stanowi użycie ES jako miejsca docelowego łańcucha, ponieważ potrzebne są tylko dwa rejestry segmentowe. Bez nich nie byłoby to zbyt użyteczne - lub zawsze wymagałoby przedrostka segmentu. Co może zabić jedną z zaskakujących funkcji, użycie (nie powtarzających się) instrukcji łańcuchowych, skutkujące ekstremalną wydajnością ze względu na ich kodowanie jednobajtowe.

* 2 - Z perspektywy czasu „Wszystko inne Segment” byłoby o wiele lepszym nazewnictwem niż „Dodatkowy segment”.

* 3 - Zawsze ważne jest, aby pamiętać, że 8086 był pomyślany tylko jako środek zatrzymania przerwy do czasu ukończenia 8800 i był przeznaczony głównie dla świata wbudowanego, aby zatrzymać klientów 8080/85 na pokładzie.


1
Wow, dziękuję za wyjaśnienie tego wszystkiego! To wiele wyjaśnia i ma sens! +1
user541686
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.