14loadal.txt Nedokumentovana instrukce LOADALL v procesorech 80286 a 80386 ============================================================= (C) 1991, Michal Brandejs Katedra matematicke informatiky PrF Masarykovy univerzity v Brne Instrukce LOADALL byla poprve zavedena do instrukcniho repertoaru procesoru Intel v 80286. Firma Intel ji ma zdokumentovanou pouze v materialu urcenem pro vlastni potrebu a informace o ni nesiri. Vyprojektovala ji pro testovaci ucely, ovsem jeji pouziti, jak vyplyne z nasledujiciho povidani, je daleko vsestrannejsi. Instrukci LOADALL lze jednorazove naplnit vsechny registry procesoru vcetne jejich neviditelnych casti. Instrukce se smi pouzit jak v realnem, tak i v chranenem rezimu. Navic lze pomoci LOADALL v 80286 v ramci chraneneho rezimu emulovat program v realnem rezimu 8086. V realnem rezimu muze LOADALL zajistit adresaci 15MB fyzickeho adresoveho prostoru 80286 bez prepnuti do chraneneho rezimu. Instrukce LOADALL je tesne svazana s vnitrni logikou procesoru 80286. Protoze procesor 80386 ma jinou vnitrni strukturu, nemuze zde instrukce LOADALL 80286 plnohodnotne pracovat, a proto 80386 ma navic instrukci obdobnou s jinou definici (viz dale). Instrukce LOADALL 80286 v procesoru 80386 funguje presne podle pravidel pro 80286. Autor tohoto clanku nemuze (stejne jako firma Intel) rucit za spravnost vsech zde uvedenych faktu, protoze nelze ziskat podklady autorizovane vyrobcem. Ponevadz jde o nedokumentovane instrukce, muze i firma Intel prestat tyto instrukce podporovat bez jakehokoli varovani a potom programy, ktere tyto instrukce pouzivaji, by prestaly fungovat. Programator, ktery tyto instrukce pouzije ve svem programu, ruci za svuj produkt pouze sam. Popis instrukce LOADALL pro 80286 --------------------------------- Instrukce plni obsahy vsech registru vcetne LDTR, TR, GDTR, IDTR a MSW. Take plni jinak nepristupne neviditelne casti registru ES, DS, SS, CS, TR a LDTR. Instrukci lze provest v realnem i chranenem rezimu (zde pouze na urovni opravneni 0). Kazdy pokus o provedeni LOADALL na jine urovni opravneni nez 0 zpusobi preruseni INT 13 (Obecna chyba ochrany) s chybovym kodem 0. Instrukce LOADALL dovoluje primo plnit bazi, limit a pristupova prava v neviditelnych castech segmentovych registru bez ohledu na hodnotu selektoru a tabulky popisovacu. Tyto hodnoty lze menit i v realnem rezimu opet bez ohledu na puvodni nastaveni odpovidajici realnemu rezimu. Pri plneni neviditelnych casti registru nejsou provadeny zadne kontroly (na pristupova prava). Jakmile jsou instrukci LOADALL nove hodnoty zavedeny, jsou ihned pouzivany pro vypocty bazi, kontrolu limitu a pristupovych prav v chranenem rezimu a vypocty bazi v realnem rezimu. Instrukce LOADALL ma operacni kod delky dve slabiky 0Fh 05h (slabika 0Fh je na nizsi adrese). Trvani instrukce LOADALL je 195 hodinovych cyklu a behem te doby je provedeno 51 cyklu sbernice. Instrukci LOADALL nelze v 80286 provest prepnuti z chraneneho rezimu do realneho. Jakmile je v 80286 jednou chraneny rezim zapnut (nastavenim bitu PE na jednicku v registru MSW), musi byt instrukci LOADALL plnen registr MSW tak, ze ma v bitu PE jednicku. Jedinou moznosti jak prepnout zpet do realneho rezimu je aktivovani signalu RESET. Popis bloku s informacemi pro LOADALL 80286 ------------------------------------------- Instrukce LOADALL cte blok pameti zacinajici na fyzicke adrese 000800h (2048), dlouhy 102 slabik. Tento blok obsahuje novy stav vsech registru procesoru 80286. Fyzicka adresa v pameti (sestnactkove) Prirazeny registr ----------------------- ----------------- 800-805 zadny 806-807 MSW 808-815 zadny 816-817 TR 818-819 Registr priznaku (F) 81A-81B IP 81C-81D LDT 81E-81F DS 820-821 SS 822-823 CS 824-825 ES 826-827 DI 828-829 SI 82A-82B BP 82C-82D SP 82E-82F BX 830-831 DX 832-833 CX 834-835 AX 836-83B ES neviditelna cast 83C-841 CS neviditelna cast 842-847 SS neviditelna cast 848-84D DS neviditelna cast 84E-853 GDTR 854-859 LDT neviditelna cast 85A-85F IDTR 860-865 TSS neviditelna cast Instrukce LOADALL nepristupuje k obsahum tabulek GDT, LDT a IDT, a proto take neprovadi zadne kontroly na nove obsahy neviditelnych casti registru. Hodnoty, kterymi byly naplneny neviditelne casti registru, jsou v nich zachovany az do zmeny selektoru prislusneho registru. Potom se prepisi podle platneho obsahu prislusne tabulky. V realnem rezimu jsou dolni 4 bity a horni 4 bity adresy baze nastaveny na nulu (bity 19-4 jsou nastaveny na adresu segmentu podle pravidel realneho rezimu). Limit segmentu je nastaven na 0FFFFh a pristupva prava jsou nastavena jako pro segment, do nehoz je povoleno zapisovat. V chranenem rezimu jsou baze, limit a pristupova prava naplneny podle prislusne tabulky popisovacu. Neviditelne casti maji v tabulce pro LOADALL tento format: Slabiky 0-2: 24bitova fyzicka adresa baze segmentu. Slabiky jsou ulozeny ve vzestupnem poradi (nejnizsi vyznamova slabika na nejnizsi adrese). Slabika 3: Slabika pristupovych prav. Ma stejny tvar jako v popisovaci segmentu. Jediny rozdil je v chapani obsahu bitu P (Present). Je-li nula, je obsah neviditelne casti neplatny a kazde jeho pouziti vyvola preruseni INT 13 (Obecna chyba ochrany) s chybovym kodem nula. Naplneni neviditelne casti neplatnym selektorem nezpusobi okamzite preruseni, nybrz prerusi se az v okamziku pouziti takoveho selektoru. Neviditelna cast CS muze byt instrukci LOADALL naplnena pristupovymi pravy popisovace datoveho segmentu, do ktereho lze zapisovat. Slabiky 4-5: 16bitovy limit segmentu. Interpretace obsahu tohoto 16bitoveho slova je urcena obsahem slabiky pristupova prava (viz ED). Datove segmenty rostouci smerem dolu jsou zpravidla zasobniky. Registry GDTR a IDTR maji v tabulce pro LOADALL stejny tvar jako neviditelne casti segmentovych registru s tim, ze slabika pristupovych prav (cislo 3) obsahuje nulu. Aby program po provedeni instrukce LOADALL spravne fungoval, musi byt pri vytvareni datove struktury pro LOADALL pamatovano na to, ze: 1. do segmentu se zasobnikem se musi smet zapisovat (W=1) a musi byt pritomen v pameti (P=1), 2. instrukcni segment s programem muze byt techto tri typu: pouze proveditelny (instrukcni segment s R=0), proveditelny s povolenym ctenim (instrukcni segment s R=1) a datovy s povolenym ctenim a zapisem (datovy segment W=1 a ED=0). Pro chraneny rezim navic musi byt zajisteno nasledujici: 3. identifikator DPL v neviditelne casti CS (CPL) musi byt roven DPL v neviditelne casti SS, 4. identifikatory DPL z ES a DS by mely byt nastaveny zpravidla na 3. Spousteni programu realneho rezimu v chranenem rezimu ----------------------------------------------------- Diky existenci instrukce LOADALL mohou byt v chranenem rezimu procesoru 80286 spousteny programy urcene pouze pro realny rezim procesoru x86/88 se vsemi kontrolami, ktere jsou v chranenem rezimu dostupne. V chranenem rezimu lze emulovat obsah segmentovych registru takovy, jaky by byl v rezimu realnem. Adresovy prostor takoveho programu muze byt omezen na 1 MB a umisten kdekoli v 16MB fyzickem adresovem prostoru. Dalsi odstavce popisuji nekolik akci, ktere je vhodne pred takovou emulaci provest. Uprava adresoveho prostoru Nutnost upravy adresoveho prostoru pro spousteni programu realneho rezimu v rezimu chranenem vyzaduje "hlidani" vsech zmen obsahu vsech segmentovych registru. Hlidat lze tehdy, pokud kazda instrukce plnici segmentovy registr zpusobi preruseni (poruseni ochrany). Ze se jedna o preruseni vyvolane plnenim segmentoveho registru, rozezname podle obsahu chyboveho slova, ktere ma bity 0-1 nulove a bity 2-15 nenulove. Takove preruseni ulozi do zasobniku adresu ukazujici na instrukci, ktera preruseni zpusobila. Vsechny instrukce, ktere neplni segmentovy registr, pracuji na plne rychlosti (tzn. neprerusuji). Rutina obsluhujici preruseni vyvolane plnenim segmentoveho registru musi interpretovat instrukci plnici segmentovy registr tak, ze podle plnene hodnoty nastavi datovou strukturu pro LOADALL. Potom pomoci LOADALL naplni neviditelnou cast a tim programu zpristupni datovou oblast tak, jak by to bylo v realnem rezimu. Aby se pri plneni segmentoveho registru generovalo preruseni 13 (Obecna chyba ochrany), je treba nastavit popisovacum LDT a GDT vyssi uroven opravneni nebo chybny limit segmentu s LDT a GDT. Preruseni ovsem nezpusobi naplneni segmentoveho registru selektorem v intervalu 0000h az 0003h, protoze jde o neplatny selektor, kterym muze byt registr naplnen vzdy. Preruseni misto toho vsak vyvola jakykoli odkaz na pamet s takovou hodnotou adresy segmentu (preruseni 13 s chybovym slovem 0). Tento pripad obsluzna rutina rozpozna tak, ze DS nebo ES obsahuje cislo v intervalu 0 az 3. Emulovany adresovaci prostor 8086/88 muze byt alokovan kdekoli v 16MB fyzickem adresovacim prostoru 80286 prictenim 24bitove baze k 20bitove adrese vypoctene ze segmentu realneho rezimu. Simulovani tabulky prerusovacich vektoru Dalsim rozdilnym rysem realneho a chraneneho rezimu je format tabulky urcene obsluze preruseni. V realnem rezimu tabulka prerusovacich vektoru obsahuje pro kazde preruseni <0;255> ctyri slabiky s adresou vstupniho bodu obsluzne rutiny. V chranenem rezimu kazda polozka IDT obsahuje popisovac brany. Instrukce LOADALL dovoluje simulovat tabulku prerusovacich vektoru v chranenem rezimu za toho predpokladu, ze kazde preruseni programu pracujiciho v emulovanem realnem rezimu vyvola dalsi preruseni INT 13 (Obecna chyba ochrany). Toto zajistime nastavenim DPL vsech bran v IDT na mensi hodnotu, nez je CPL emulovaneho programu. Chybove slovo potom obsahuje index do tabulky popisovacu a nulovy bit EX. Instrukce INT z emulovaneho realneho programu muze byt potom simulovana obsluznou rutinou preruseni INT 13. Tato rutina nahledne do tabulky prerusovacich vektoru a precte prerusovaci vektor odpovidajici generovanemu preruseni. Rutina ulozi stav programu do zasobniku a preda rizeni na adresu prectenou z tabulky prerusovacich vektoru. Podobnym zpusobem lze obslouzit i externi preruseni. Rutina chraneneho rezimu, ktera obsluhuje preruseni, musi vsak jednoznacne urcit, zda je preruseni urceno emulovanemu programu nebo jinemu procesu chraneneho rezimu. Povoleni zapisu do segmentu s programem Zapisy do segmentu s instrukcemi jsou umozneny tehdy, je-li segment oznacen jako W=1 (z toho plyne, ze musi jit o datovy segment, coz jde instrukci LOADALL nastavit). Potom jsou povoleny vsechny zapisy se segmentovym prefixem CS. Povoleni uchovavani pomocnych hodnot do segmentovych registru Naplneni segmentoveho registru pomocnou hodnotou, ktera nekoresponduje s zadnym platnym popisovacem, vyvola preruseni INT 13. V takovem pripade lze v obsluzne rutine pomocnou hodnotou naplnit viditelnou cast segmentoveho registru a neviditelnou cast oznacit jako chybnou (P=0). Tim se znemozni pouziti neviditelne casti pro transformaci adresy. To znamena, ze jsou povoleny instrukce typu MOV AX,ES, ale nejsou povoleny MOV AX,ES:[BX]. Existence takove vlastnosti vyzaduje, aby obsluzna rutina byla schopna rozpoznat, zda jde o plneni segmentoveho registru pomocnou hodnotou nebo platnou adresou segmentu. Rutina podle toho musi spravne nastavit viditelnou a neviditelnou cast segmentoveho registru v datove strukture pro LOADALL. Po provedeni LOADALL musi predat rizeni na prikaz bezprostredne za instrukci plneni segmentoveho registru. Kontrola V/V operaci V/V operace, ktere provadi emulovany realny program, lze kontrolovat diky existenci indikatoru IOPL. Je-li IOPL 0038 LDT_REG SELEKTOR 003C GS_REG SELEKTOR 0040 FS_REG SELEKTOR 0044 DS_REG SELEKTOR 0048 SS_REG SELEKTOR 004C CS_REG SELEKTOR 0050 ES_REG SELEKTOR 0054 TSS_DESC NEVIDITELNA_CAST 0060 IDT_DESC NEVIDITELNA_CAST <0,0,?,?> 006C GDT_DESC NEVIDITELNA_CAST <0,0,?,?> 0078 LDT_DESC NEVIDITELNA_CAST 0084 GS_DESC NEVIDITELNA_CAST 0090 FS_DESC NEVIDITELNA_CAST 009C DS_DESC NEVIDITELNA_CAST 00A8 SS_DESC NEVIDITELNA_CAST 00B4 CS_DESC NEVIDITELNA_CAST 00C0 ES_DESC NEVIDITELNA_CAST 00CC Delka tabulky Pro upresneni uvedeme jeste popis neviditelne casti registru: 95 63 31 23 12 7 0 +----------------+-----------------+---+--------------+---+---+ | 32bitovy limit | 32bitova baze | 0 | Prist. prava | 0 | 0 | +----------------+-----------------+---+--------------+---+---+ Dvojslovo na nejnizsi adrese (Pristupova prava) obsahuje tyto informace: ++++++++----------------------------- 0=nedefinovano |||||||| +--------------------------- Present 0=ne 1=ano |||||||| |++------------------------- DPL |||||||| |||+------------------------ Popisovac 0=syst. 1=Inst/Data |||||||| ||||+++--------------------- Typ (*) |||||||| ||||||+-----------------------Cteni/zapis (W) 0=C 1=C/Z |||||||| |||||+|-----------------------Rozsirovani (ED) 0=Nahoru 1=Dolu |||||||| ||||+||-----------------------Proveditelny 0=Ne 1=Ano (*) |||||||| ||||||| 000=Cteni |||||||| ||||||| 001=Cteni/Zapis |||||||| ||||||| 010=Cteni, rozsiritelny dolu |||||||| ||||||| 011=Cteni/Zapis, rozsir. dolu |||||||| ||||||| 100=Proveditelny |||||||| ||||||| 101=Proveditelny/Cteni |||||||| ||||||| 110=Proveditelny, konformni |||||||| ||||||| 111=Proveditelny/Cteni, konform. |||||||| |||||||+-------------------- Zpristupnen (A) |||||||| |||||||| +------------------ 0=nedefinovano |||||||| |||||||| |+----------------- Implic. velikost operandu (+) |||||||| |||||||| || 0=16bitove operandy |||||||| |||||||| || 1=32bitove operandy |||||||| |||||||| || |||||||| |||||||| ||++++++-++++++++-- 0=nedefinovano |||||||| |||||||| |||||||| |||||||| |||||||| |||||||| |||||||| |||||||| 3||||||||2||||||||1||||||||0||||||||0 1||||||||3||||||||5||||||||7||||||||0 bit +++++++++++++++++++++++++++++++++++++ | Intel |22221111|11|Intel| Intel | (*) = CS muze byt oznacen jako datovy | rezerv.|32109876|54| rez.| rezerv.| segment s ctenim i zapisem +++++++++++++++++++++++++++++++++++++ pouze instrukci LOADALL. (+) = Pouzitelne pouze pro CS. Vlastnich 11 bitu pristupovych prav lze popsat take zvlast pro jednotlive typy segmentu: 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 1 1 1 1 1 1 1 3 2 1 0 9 8 7 6 5 4 3 3 2 1 0 9 8 7 6 5 4 3 +-+---+-+-----+-+-+-+-+ +-+---+-+-----+-+-+-+-+ |P|DPL|S| Typ |A|0|G|D| |P|DPL|S| Typ |0|G|D| | | | |0| | | | | | | | | | | |1| | | | | | | | +-+---+-+-----+-+-+-+-+ +-+---+-+-----+-+-+-+-+ Bit: P (Present) 1=segment je v pameti, 0=neni v pameti. DPL (Descriptor Privilege Level) 0=nejvyssi, 3=nejnizsi. S (System) 0=segment je instr. nebo datovy, 1=systemovy. Typ Typ segmentu (S=0): +-+-+-+ | | | | +-+-+-+ | | | | | +-- Cteni/Zapis (W) 0=Cteni 1=Cteni/Zapis | +---- Smer rozsirovani (ED) 0=Nahoru 1=Dolu +------ Proveditelny 0=Datovy seg. 1=Instr. seg. Typ Typ segmentu (S=1): 0000 = nepouzito 0001 = TSS neaktivniho procesu 80286 0010 = LDT 0011 = TSS aktivniho procesu 80286 0100 = brana pro predani rizeni 80286 0101 = brana zpristupnujici TSS 0110 = brana pro maskujici preruseni 80286 0111 = brana pro nemaskujici preruseni 80286 1000 = nepouzito 1001 = TSS neaktivniho procesu 80386 1010 = nepouzito 1011 = TSS aktivniho procesu 80386 1100 = brana pro predani rizeni 80386 1101 = nepouzito 1110 = brana pro maskujici preruseni 80386 1111 = brana pro nemaskujici preruseni 80386 A (Accessed) (S=0) segment 0=nebyl zpristupnen 1=byl zpristupnen G (Granularity) jednotkou limitu je 0=slabika 1=4KB Prepocet limitu v jednotkach 4 KB na jednotky 1 B se provede touto posloupnosti instrukci: SHL Limit,12 OR Limit,0FFFh D (Default) implicitni velikost operandu je 0=16 bitu, 1=32 bitu Je-li nastaven, interpretuje CPU vsechny operandy a adresy jako 32bitove. Tento bit se vztahuje pouze na registr CS. K vyse uvedenym informacim uz jenom nekolik poznamek: 1. Stejne jako v 80286 je bit oznaceny P (Present) uvnitr neviditelne casti chapan ve smyslu platnosti obsahu tohoto registru. Pouzitim LOADALL lze bit P vynulovat. 2. Hodnotu CPL urcuje DPL registru SS a CS. 3. DPL registru DS, ES, FS a GS by mela byt 3. 4. Hodnota bitu G nema zadny efekt na tvar ulozeni limitu v neviditelne casti registru. 5. Instrukcni segment muze byt typu Cteni/Zapis/Proveditelny pouze nastavenim pristupovych prav na datovy segment s povolenym zapisem a ED=0 instrukci LOADALL. Na zaver jeste poznamenejme, ze v pocitacich IBM PC/AT lze k pameti, jejiz fyzicke adresy jsou vetsi nez 1 MB, pristupovat pouze tehdy, je-li to povoleno signalem Gate A20 (viz 15A20.doc). Toto neni vlastnost procesoru, nybrz pocitace PC/AT. Po RESETu pocitace je pristup k vyssim adresam zakazan. Povoluji jej teprve programy, ktera tuto pamet pouzivaji (RAMDRIVE.SYS, HIMEM.SYS, ...). Mimochodem, i v ovladacich RAMDRIVE.SYS a HIMEM.SYS najdete instrukci 0Fh 05h.