osdev.labedz.org

Prawie bez zmian od 26 lat...

Procesor 80386 w trybie rzeczywistym wykonuje kod przeznaczony dla procesorów 8086, 8088, 80186, 80188 lub kod przeznaczony dla trybu rzeczywistego procesora 80286. W rzeczywistości, architektura procesora pracującego w tym trybie jest praktycznie identyczna z w/w procesorami. Dla programisty, procesor 80386 w tym trybie przedstawia się jako szybki 8086 z rozszerzeniami dotyczącymi rejestrów i trybów adresowania oraz nowymi instrukcjami.

Tworzenie adresu fizycznego

Procesor 80386 udostępnia jeden megabajt + 64 KB przestrzeni adresowej dla programów w trybie rzeczywistym. Przekształcenie adresu segmentu dokonywane jest dokładnie tak samo jak w procesorach starszych: 16-bitowa wartość selektora segmentu jest przesuwana w lewo o cztery bity i w ten sposób tworzy adres bazowy segmentu. Adres efektywny jest rozszerzany o cztery najstarsze bity o wartości 0 i dodawany jest do adresu bazowego, co tworzy adres liniowy (adres liniowy odpowiada adresowi rzeczywistemu, gdyż w trybie rzeczywistym nie występuje stronicowanie pamięci) - patrz rysunek. W przeciwieństwie do procesora 8086, wynik adresu liniowego może posiadać do 21 znaczących bitów, gdyż istnieje prawdopodobieństwa wystąpienia przeniesienia podczas dodawaniu adresów. W procesorze 8086 bit przeniesienia jest obcinany, natomiast w procesorze 80386 jest on zapamiętywany na bicie 20 adresu liniowego.

Tworzenie adresu fizycznego w trybie rzeczywistym
Rys. Tworzenie adresu fizycznego w trybie rzeczywistym

Istnieje również możliwość wygenerowania 32-bitowego adresu efektywnego (poprzez zastosowanie prefiksu wielkości adresu), jednakże przekroczenie wartości 65536 powoduje wywołanie wyjątku. Dla pełnej zgodności z trybem rzeczywistym procesora 80286 wyjątki naruszenia ochrony (przerwania 12 lub 13 bez kodu błędu) występują gdy adres nie leży w przedziale 0 - 65536.

Sposób generowania adresu liniowego powoduje, że istnieje możliwość zaadresowania tej samej komórki pamięci poprzez różne wartości w rejestrach segmentowych i wskaźnikach. Na przykład pary: wartość selektora segmentu: 0x1, przesunięcie: 0x0, oraz wartość selektora segmentu: 0x0, przesunięcie: 0x10 dają ten sam adres liniowy 0x10.

Obsługa przerwań i wyjątków

Obsługa przerwań i wyjątków w procesorze Intel386 pracującym w trybie rzeczywistym odbywa się tak samo jak w procesorach 8086. Wektory procedur przerwań i wyjątków znajdują się w tablicy wektorów przerwań. Procesor, chcąc wywołać przerwanie, mnoży wartość identyfikatora przerwania lub wyjątku przez cztery, dzięki czemu otrzymuje indeks adresu procedury w tablicy przerwań. Tablica przerwań składa się z wskaźników typu 'FAR' (dalekiego skoku) wskazujących na punkty wejścia do podprocedury obsługi przerwania.

Kiedy występuje przerwanie procesor zachowuje aktualną wartość pary rejestrów CS : IP na stosie oraz flagi procesora, wyłącza przerwania, czyści flagę TF (flaga pracy krokowej), następnie przekazuje kontrole podprocedurze przerwania.

Wyjście z przerwania następuje po wywołaniu instrukcji IRET, która wykonuje czynności przeciwne jak przy wywołaniu przerwania i zwraca kontrole aplikacji.

Podstawową różnicą w obsłudze przerwań i wyjątków w procesorze Intel386 a mechanizmem tym w procesorze 8086 jest położenie tablicy przerwań. W procesorze 8086 jest ona umieszczona na początku przestrzeni adresowej (adres 0), a w 80386 położenie tablicy zależy od zawartości rejestru IDTR. Fakt ten nie jest powszechnie znany wśród programistów, prawdopodobnie dlatego, że po resecie procesora rejestr CS zawiera adres bazowy 0 i wartość limitu 0x3FF, które to wartości powoduje identyczne zachowanie się mechanizmu przerwań jak w procesorach starszych. Jednakże istnieje możliwość wywołania instrukcji LIDT w trybie rzeczywistym i załadowanie rejestru CS nowymi, odpowiednimi dla nas wartościami bazowymi i limitu. Jeśli wystąpi przerwanie, którego odpowiedni wpis w tablicy jest powyżej wartości limitu zawartego w rejestrze CS, procesor wywoła wyjątek numer osiem.