Védett mód és az assembly
A védett mód alapjaiEgy alkalmazás szempontjából a védett mód nem sokban különbözik a valós módtól. De a valós módban a memória szegmentációja automatikusan kezelödik egy beépített mechanizmus által a szegmens regiszterekkel összhangban. A szegmens regiszterek alkotják a CPU által a címbuszra küldött fizikai cím egy részét. (ld. Fig. 1(a)) A fizikai cím a következöképp számolódik: megszorozzuk a szegmens regisztert 16-al, és hozzáadjuk a 16 bites offszet regisztert. 16 bites offszeteket használva a processzort akaratunkon kívül is 64 KByteos szegmensekre limitáljuk. Egyes programok túllépik ezt a 64 KByteos megkötést, a szegmens regiszter 16-al növelésével; ezen programok védett módban futtatása nem lehetséges, mert kivételt (exception) okoznának, mivel a szegmens regiszterek máshogy értelmezödnek. Védett módban a memória szegmentációját táblák definiálják (ezek neve leíró tábla, descriptor tábla), a szegmens regiszter csak mutatókat tartalmaz a tábla bejegyzéseire. Minden táblabejegyzés 8 byte széles; így a szegmens regiszter értékei a 8 többszörösei (08h, 10h, 18h, stb.). A szegmens regiszter alsó 3 bitje definiált, de az egyszerüség kedvéért tekintsük úgy, hogy bármely program, ami a szegmens regisztert nem 8 többszörösével tölti fel, védelmi hibát okozna. Két tábla van a memória szegmentáltságának definiálására: a Globális Leíró Tábla (Global Descriptor Table = GDT), és a Lokális Leíró Tábla (Local Descriptor Table = LDT). A GDT olyan szegmentációs információkat tartalmaz, amelyet minden program elérhet. Az LDT ezzel szemben egy specifikus taszk vagy program szegmentációs információit tartalmazza. Mint az már eddigre kiderült, a szegmens regiszterek nem alkotják részét védett módban a fizikai címnek, hanem mutatóként szolgálnak a GDT vagy az LDT bejegyzéseire (ld. Fig. 1(b)). Minden alkalommal, mikor feltöltjük a szegmens regisztert, a báziscím kiolvasódik egy táblabejegyzésböl, és eltárolódik egy a programozó számára nem látható regiszterben, a szegmens leíró cache-ben. A fizikai cím, ami megjelenik a címbuszon, a 16 vagy 32 bites offszetnek a leíró táblában lévö báziscímhez adásával keletkezik. |
![]() |
||||||||||||||||||||||||||||||||||||
A valós módú alkalmazások védett módúvá átírásának következö problémája
a megszakítások használata. Valós módban a 0-ás fizikai címtöl kezdödöen
dupla word pointerek mutatnak a megszakítási rutinok fizikai címeire.
A 4a kép mutatja a megszakító rutinok címzését valós módban. Mikor egy
megszakítás generálódik, a CPU megkeresi a címét a megszakítás kezelö
rutinnak (Interrupt Service Routine = ISR) ebben a megszakítás vektor
táblában. A verembe PUSH-olt információk azonosak mind a szoftveres,
hardveres vagy CPU generált megszakításoknál. Védett módban a verembe PUSH-olt információ változhat, éppúgy, mint a megszakítási vektor báziscíme és a megszakítási tábla mérete. A megszakítási vektor visszakeresési mechanizmus szintén eltér a valós módútól. A 4b kép mutatja, hogy védett módban miként történik a megszakítások hívása. Mikor egy megszakítás generálódik, a CPU összehasonlítja a megszakítás számát (x8) az IDT méretével -- ami el van tárolva a megszakítás leíró cache regiszterben. Ha ez nem haladja meg az IDT méretét, a megszakítás hívhatónak minösül, és az IDT báziscím behívódik a leíró cacheböl; eztán az ISR védett módú címe betöltödik az IDT-böl. Az ISR címe nem egy fizikai cím, hanem egy védett módú, szegmentált cím. Az IDT-ben megadott segmens szelektor felhasználásával a CPUnak el kell végeznie mindazokat a korlát ellenörzéseket melyek a GDT-n is történnek, hogy kiszámítsa a fizikai címet. Mikor a fizikai cím kiszámolódik, a CPU PUSH-olja a FLAGS, SEGMENT, OFFSET -et és jó eséllyel egy HIBA KÓDOT (ERROR CODE) is a stackra, mielött elugrana az ISR-re. A szoftveres és hardveres megszakításoknak nem sokban kell különbözniük a valós módú párjaiktól, de a CPU által generált megszakításokat és hibákat lekezelö megszakítások lényegesen eltérnek. A CPU a megszakítások három kategóriáját generálhatja: csapdák (trap), hibák (fault), megszakítások (aborts). A stack képe kategóriáról kategóriára változó, minthogy egy hibakód pusholódik vagy sem a verembe. A csapdák sosem pusholnak hibakódot, hibák általában igen, míg a megszakítások (abort) mindíg. A csapdák (trap) hasonlóak a szoftveres megszakításokhoz. A név elég beszédes, mivel a CPU "elkapja" a kiváltó eseményt. A CPU nem tudja, hogy az esemény bekövetkezett, egészen a bekövetkezés tényéig; tehát az eseményt a megszakítás hívása elött kell elkapnia. Így az ilyen ISR-ek visszatérési címe az esemény bekövetkezte utáni utasításra mutat. Csapda pl. az osztás 0-val, adat breakpointok, és a 3-as megszakítás (INT03). Hibák (fault) olyankor jelentkeznek, ha valami rossz történt -- valami, amit ki kell javítani. A CPU azonnal tudja, hogy hiba történt és meghívja a megszakítás-generáló mechanizmust. Az ISRek ezen típusának az elsödleges célja, hogy kijavítsa a problémát, és pontosan onnan indítsa újra a programot, ahol abbamaradt. Épp ezért az ISR visszatérési címe a hibát kiváltó utasításra mutat -- így visszaállíthatóvá téve a hibát. A megszakítások (abort) a leggyakoribb típusai az interruptoknak, és nem-újraindíthatónak tekinthetöek. Hibakód pusholódik a stackra, de ez mindíg 0 lesz. A CPU stack szegmense és állapotjelzöi lehet, hogy köztes állapotban vannak, és egy megszakítás (abort) folytatására tett kísérlet elöre megjósolhatatlan viselkedéshez vezethet. Az 1. táblázat kategorizálja a CPU védett módban generált megszakításainak listáját. Az esetek többségében a CPU valós módban ugyan olyan megszakítást generálna, mint védett módban, csak soha sem pushol hibakódot a verembe. Érdekes kérdés, hogy a BIOS miért nem használható védett módban. Azt gondolhatnánk, egyszerü módfüggetlen kódot írni, csak ne használjunk távoli ugrásokat és távoli hívásokat ("FAR JUMP","FAR CALL"). De sajnos nem ilyen egyszerü, hogy követjük ezeket a megkötéseket. A felsoroltak kerülése mellett az ISRnek el kellene távolítania a verembe pusholt hibakódot is. Itt kezdödnek a problémák, mert ezek csak védett módban kerülnek oda; tehát detektálnunk kell, hogy védett módban vagyunk-e, mielött kivennénk a hibakódot... Ennek megállapításához hozzá kell férnünk a gép státusz wordhoz (machine status word = MSW), vagy a rendszer regiszterhet (system register, CR0). Az MSW elérése bármely privilégiumszinten történhet, de a CR0 elérése csak a legmagasabb privilégium szinten történhet -- 0. szint. Ha a felhasználói program alacsonyabb szinten fut a 0-nál, akkor nem érhetjük el a regisztert. Viszont megvalósítható, ha speciális "call gate"-t használunk, ami lehetövé teszi számunkra a szint megváltoztatását az ISR hívása elött. Ez persze nem szükséges, ha az SMSW (Store Machine Status Word) utasítást használjuk. De a probléma még ezzel sem megoldott, tegyük fel, hogy a program egy valós módú értéket hagyott a szegmens regiszterek bármelyikében. Ha az ISR PUSH-ol, majd ennek megfelelöen POP-ol bármely ilyen regisztert, a POP arra fogja késztetni a CPUt hogy szegmenst keressen ki vagy a GDTböl, vagy az LDTböl. Nagy valószínüséggel a valós módú érték védelmi hibát fog kiváltani (protection error). Tehát a BIOS használata védett módban szinte lehetetlen. Ha viszont lett volna definiálva egy szabályhalmaz, amit minden programozó és operációs rendszer követne, akkor megvalósítható volna. 4(a) kép -- Megszakítás kiszolgáló címzés Valós Módban 4(b) kép -- Megszakítás kiszolgáló címzés Védett Módban
|