2013-03-11 15 views
8

Potrzebuję zmodyfikować niektóre dll, ale nie wiem, co dokładnie robi rejestrów segmentów (DS, SS, ...) w trybie chronionym. Nauczyłem się w szkole prawdziwego 16-bitowego trybu, w którym rejestracja segmentów mnoży się przez 16 i offset w normalnym rejestrze daje efektywny adres w pamięci fizycznej. W trybie chronionym istnieje pewien płaski model pamięci i pamięć wirtualna, gdzie każdy proces "ma" pamięć 4 GB, więc jeśli rejestry mają 32-bitowe, to mogę adresować każdy bajt pamięci wirtualnej tylko przez rejestr "offset". Więc który puproses mają rejestry segmentowe w trybie chronionym, na przykładJaki jest cel rejestrów segmentów w trybie chronionym x86?

mov eax, dword ptr ds:[20037DA0] 
+0

Jakiego disasemblera używasz? Być może domyślnie zawsze wyprowadza i pokazuje rejestr segmentów w oparciu o kod operacyjny, nawet jeśli pamięć nie jest podzielona na segmenty. – Michael

+0

@Michael: Używam ollydbg – Krab

+1

Pamięć jest nadal podzielona na segmenty, mimo że najbardziej popularne systemy operacyjne używają tylko jednego segmentu i ustawiają wszystkie rejestry segmentów na tę samą wartość. –

Odpowiedz

6

basicaly cel jest taki sam jak w trybie rzeczywistym z wyjątkiem sposób ich działania jest nieco inny. DS w twoim przykładzie wybiera jeden deskryptor pamięci w GDT (google ten termin, jeśli naprawdę chcesz to zrozumieć, "Globalna tabela deskryptorów"), który zawiera informacje takie jak adres bazowy, adres końcowy, szczegółowość itp. Twoje przesunięcie jest następnie dodawane do adresu bazowego , koniec. Jeśli pracujesz w systemie Windows (założę się, że jest to taki sam system Linux), nie musisz się martwić o te rejestry segmentów, ponieważ powiedziałeś, że jest to płaski model, co oznacza, że ​​powinien być tylko jeden deskryptor dla całej pamięci, więc jeśli nie zmieniasz te rejestry powinny działać tak, jakby nie istniały.

+0

Istnieje kilka ważnych różnic w korzystaniu z rejestrów segmentów między trybem rzeczywistym i modelem chronionym, które należy wziąć na konto. Na przykład, w trybie chronionym użycie nadpisania segmentu 'ss:' może spowodować błąd segmentacji, więc nie można użyć żadnego innego rejestru z wyjątkiem 'esp' i' ebp' jako rejestru podstawowego w adresowaniu stosu. W trybie rzeczywistym możesz adresować stos z dowolnymi rejestrami, korzystając z '' '' '' 'override". – nrz

+0

Hmm, poprawny punkt, ale do celów odczytu/zapisu stosu, wierzę, że możesz użyć funkcji ds: offset, a także mieć ten rejestr, który chcesz zsynchronizować. Pod warunkiem, że punkty przesunięcia do stosu oczywiście. – Pyjong

+2

@nrz Natomiast 'ds/es.base' może zdecydowanie różnić się od' ss.base' (najbardziej podstawowy powód, dla którego nie można byłoby używać tych segmentów zamiennie), to byłaby dość rzadka konfiguracja w trybie chronionym 32-bitowym i prawdopodobnie wymagałaby dodatkowych instrukcji do przekazywania adresów lokalnych zmiennych w C/C++ (musisz uwzględnić różnicę bazową segmentu, aby dostęp do locals był możliwy za pośrednictwem 'ds' w wywołanych funkcjach, tak jak globale). –

5

Niektóre tło historyczne

8086 zawsze stałą Okno 64Kb na segment, który począwszy od adresu została obliczona poprzez rejestru segmentowego (* 16). Od 80286 istnieją specjalne tabele w pamięci (GDT i LDT). Tabele zawierają adres początkowy, długość i prawa dostępu do segmentu. Rejestry segmentów (CS, DS, ES, SS - a od 80386: FS, GS) zawierają indeksy do tych tabel.

Teoretycznie system operacyjny może ustawić przesunięcie i długość segmentu w taki sposób, w jaki chce to zrobić: W przypadku modelu 8086 DS = 0xoznacza: Segment ma wartość 64 KB od adresu 0x. W trybie 32-bitowym DS = 0xmoże oznaczać: Początek segmentu pod adresem 0xABCD, długość to bajty 0xEF - zależy to od zawartości tabel GDT i LDT utworzonych przez system operacyjny. Próba uzyskania dostępu do segmentu spoza tego zakresu (DS: 0x1000, jeśli długość to < 0x1000) spowoduje wyjątek (przerwanie).

Obecna sytuacja

Jednak najbardziej nowoczesne systemy operacyjne 32-bitowe naprawdę nie używać segmentu rejestruje więcej. Ich wartości są ustawiane w zależności od trybu (jądra lub użytkownika) z powodu problemów z prawami dostępu. Początkowy adres wynosi zazwyczaj 0, a długość 4GiB.

Rzeczywistą ochronę pamięci wykonuje się za pomocą MMU, dzięki czemu do niektórych obszarów pamięci nie można uzyskać dostępu w trybie użytkownika. W nowoczesnych systemach operacyjnych MMU jest absolutnie skuteczna. Mapuje "bezwzględny" adres wirtualny na rzeczywisty adres fizyczny sprawdzający naruszenia praw dostępu.

Jest jeden wyjątek: Niektóre systemy operacyjne (na przykład Windows i Linux) używają segmentów FS i/lub GS, aby wskazać inny obszar pamięci.

Z tego powodu w trybie 64-bitowym procesory x86 używają rejestru CS tylko dla problemów z prawami dostępu, a FS i GS mogą być używane do dodawania przesunięcia do każdego adresu. O ile wiem, DS, ES i SS nie są używane, podczas gdy zawartość rejestrów FS i GS nie ma znaczenia, ale istnieją specjalne rejestry, które wyraźnie dają przesunięcie do dodania do operacji, która używa FS lub GS.

+0

FS służy do obsługi wyjątków w systemie Windows. Ramka stosu jest tam zapisywana, więc program obsługi wyjątków może znaleźć drogę powrotną. – Devolus

+0

@Devolus To nie tylko obsługa wyjątków. Bardziej ogólnie, 'FS' wskazuje na [** TIB **] (http://en.wikipedia.org/wiki/Win32_Thread_Information_Block). –

+1

W trybie 64-bitowym cs, ds, es i ss już nie istnieją. Działają tylko fs i gs. – Nubok

0

Dam ci prostą odpowiedź, ale dla dalszych informacji polecam poniższy link do dokumentów architektury AMD, bardzo łatwa lektura.PS: Nie omówiłem tutaj Xeon ani PAE.

Architektura IA-32 (x86) ma 32-bitową magistralę adresową dla pamięci RAM.

32-bitowa magistrala jest dodatkowo podzielona na 2 x 16-bitowe segmenty, z których każdy może uzyskać dostęp do 2 GB pamięci RAM w sumie 4 GB.
Nazywa się to przełączaniem banku pamięci.

W celu umożliwienia ochrony Intel wraz z MS postanowił użyć jednego segmentu dla trybu jądra, a drugi dla trybu użytkownika - i dlatego Windows historycznie miał przestrzeń adresową trybu 2GB. Jest to ograniczenie sprzętowe x86, a nie ograniczenie Windows.

Segment rejestruje oddzielone przestrzenie jądra i adresy przestrzeni użytkownika. W ten sposób wdrożono ochronę pamięci.

Co więcej, IA-32 generał miał również 32-bitowe rejestry wewnętrzne, więc nie mógł się na nie zapisać. To jest tryb rzeczywisty (bez tłumaczenia adresu).

Paging wymaga 36 bitów Myślę, że (nie cytuj mnie), to tam przyszedł IA32e. Dodatkowe bity na IA-32e pozwoliły na stronicowanie z dysku twardego, jest to jedyny sposób, w jaki można go uruchomić na systemie Windows x64, ponieważ x64 wymaga NX i znajduje się na bit 63.

Proszę przeczytać dokumenty architektoniczne AMD, osobiście uważam, że są bardziej przydatne niż wersje Intela.

http://developer.amd.com/wordpress/media/2012/10/24593_APM_v21.pdf

PS z pamięcią płaskiej AMD64 została wprowadzona, rezygnacji z segmentów.

Jednak 32-bitowe procesy nadal wymagają rejestrów segmentów. Na AMD64, gdy proces 32-bitowy trafia na szczyt stosu, wskaźnik jest rzucany do adresu bazowego w nowym rejestrze segmentów. W ten sposób 32-bitowe aplikacje mogą skutecznie jeść tyle pamięci RAM, ile chcą, bez ograniczeń. Oraz w granicach ofc ... :)

Mam nadzieję, że to pomaga.