Wat is Protected Mode en waarmee wordt het gegeten. Overschakelen van Intel-processors naar beschermde modus Overschakelen naar beschermde modus assembler

rPUME OEDEMSHOPZP RETETSHCHB CHOPCHSH NPZH PVTBPCHBFSH CHBU OPCHSHCHN CHSHCHHRHULPN UCHPEK TBUUSCHMLY.

yFBL, LBL CHSH RPNOYFE, H TEBMShOPN TETSYNE TBVPFSCH RTPGEUUPTB OBN DPUFKHREO CHUEZP MYYSH 1 NEZBVBKF BDTEUOPZP RTPUFTBOUFCHB (Yb LPFPTSCHI PVSHCHUOPK RBNSFSHA SCHMSEFUS CHUEZP LYYSH 64). fBL LFP Y VSHMP CHP READING RETCHSHCHI RTPGEUUPTPCH CHTPDE 8086, OP RPUFEREOOP PVYaЈNB PRETBFICHOPK RBNSFY UFBMP OE ICHBFBFSH. h FP TSE CHTENS FTEVPCHBMPUSH UPITBOYFSH RPMOHA PVTBFOHA UPCNEUFYNPUFSH, UFPVShch 16-TBTSDOSHCHE PRETBGYPOOSCHE UYUFENSCH CHTPDE DOS UNPZMY OPTNBMSHOP TBVPFBFSH. rPFPNKh VSCHM CHCHEDIO OPCHSHCHK TETSYN TBVPFSCH RPGEUUPTB - BEEYEIIOOSCHK TETSYN. rPUME RETEIPDB CH OEZP DMS BDTEUBGYY YURPMSHHEFUS OE 16, B 32 YMY DBTSE 64 VYFB, B UEZNEOFSHCH UFBTPN RPOINBOY YUYUEBAF. fBLCE DPVBCHMSAFUS BEIFOSCHE NEIBOYNSCH (YNEOOP RPFPNH BEEYEIOOSCHK TETSYN), UFPVShch SDTP pu VShchMP YЪPMYTPCHBOOP PF RTYMPTSEOIK Y NPZMP YNY UCHPVPDOP HRTBCHMSFSH. sFP OEVPVIPDYNP MAVPK RPMOPGEOOPK NOPZPЪBDBYuOPK UYUFENE.

оБЮОЈН У ФПЗП, ЮФП ДПВБЧМСЕФУС Ч ТЕБМШОПН ТЕЦЙНЕ ОБ РТПГЕУУПТБИ, ЛПФПТЩЕ РПДДЕТЦЙЧБАФ 32-ВЙФОЩК БДТЕУ (i386 Й ЧЩЫЕ) - ДПВБЧМСАФУС ОПЧЩЕ ТЕЗЙУФТЩ, ЧЕТОЕЕ ТБУЫЙТСАФУС УФБТЩЕ: EAX, EBX, ECX, EDX, ESP, EBP, EIP, ESI, EDI, EFLAGS. LBL NPTsOP DPZBDBFSHUS, LFP 32-VYFOSHCHE CHETUYY PVSCHYUOSCHI TEZYUFTCH TEBMSHOPZP TETSYNB (L YNEOY TEZYUFTB DPVBCHMSEFUS RTYUFBCHLB "E"). CHUE LFY 32-VYFOSHCHE TEZYUFTSHCH LTPNE EIP DPUFKHROSCH Y CH TEBMSHOPN TETSYNE, OP CH FBLPN UMHYUBE VHDHF OBOYNBFSH OB 1 VBKF VPMSHYE (LEYN DPVBCHMSEFUS UREGYBMSHOSHCHK RTEZHYLU). over RTPGEUUPTE NPMPTS 286 FY LPNBODSCH VHDHF OELPTTELFOSCH. nSch NPTSEN, OBRTYNET, OBRYUBFSH mov eax, 0x12345678 Y RPUME LFPZP H AX VKhDEF 0x5678, RPFPNH UFP ON LBL VSCHMSEFUS "PLOPN" H NMBDYHA YUBUFSH TEZYUFTTB EAX (BOBMPZYUOP, AL NMBDY AX). тЕЗЙУФТБ-ПФПВТБЦЕОЙС УФБТЫЕК ЮБУФЙ 32-ВЙФОЩИ ТЕЗЙУФТПЧ ОЕ УХЭЕУФЧХЕФ - НПЦОП ЕЈ ЙЪЧМЕЮШ ФПМШЛП У РПНПЭША БТЙЖНЕФЙЛЙ (ОБРТЙНЕТ, УДЧЙОХФШ EAX ОБ 16 ВЙФ ЧРТБЧП У РПНПЭША shr eax, 16, ФПЗДБ Ч AX ВХДЕФ УФБТЫБС РПМПЧЙОБ, ОП УПДЕТЦЙНПЕ НМБДЫЙИ ВЙФ ВХДЕФ ХФЕТСОП). юФП ИБТБЛФЕТОП, Ч ЪБЭЙЭЈООПН ТЕЦЙНЕ ОБПВПТПФ, ЛПНБОДЩ ТБВПФЩ У 16-ВЙФОЩНЙ ТЕЗЙУФТБНЙ (ОП ОЕ 8-ВЙФОЩНЙ) ФТЕВХАФ РТЕЖЙЛУ, РПЬФПНХ ОЕУНПФТС ОБ ФП, ЮФП ТБЪТСДОПУФШ Ч ДЧБ ТБЪБ ВПМШЫЕ, Ч ЪБЭЙЭЈООПН ТЕЦЙНЕ ВЩУФТЕЕ ЧЩРПМОСАФУС Й ЪБОЙНБАФ НЕОШЫЕ НЕУФБ ЙНЕООП ЛПНБОДЩ 32- VYFOPC BTYZHNEFILY.

fBLCE, FERETSCH H OBU OB 2 UEZNEOFOSHCHI TEZYUFTB VPMSHIE - GS TH FS. TBVPFB U ONYY RPMOPUFSHHA BOBMPZYUOB DS JA Y CH NPTSEFE YI UCHPPVPDOP YURPMSHЪPCHBFSH CH TEBMSHOPN TETSYNE. пФМЙЮЙЕ ФПМШЛП Ч ФПН, ЮФП ОЙЛБЛЙЕ ЛПНБОДЩ ЙИ СЧОП ОЕ РПДТБЪХНЕЧБАФ (DS ЙУРПМШЪХЕФУС РП ХНПМЮБОЙА РТБЛФЙЮЕУЛЙ ЧУЕНЙ ЛПНБОДБНЙ Й ОЕЛПФПТЩНЙ УФТПЛПЧЩНЙ ПРЕТБГЙСНЙ, ES ОЕЛПФПТЩНЙ УФТПЛПЧЩНЙ ПРЕТБГЙСНЙ) Й ОБДП СЧОП ХЛБЪЩЧБФШ, ЮФП ЧЩ ИПФЙФЕ ПВТБЭБФШУС ЮЕТЕЪ ОЙИ. BRIGHTNET, bewegende bijl, .

rPNYNP LFPZP TBUYTEOYS TEZYUFTCH, DPVBCHMSAFUS OPCHSHCHE HRTBCHMSAEIE TEZYUFTSHCH (TBOSHIE CHMYSM OVER TETSYN TBVPFSCH RTPGEUUPTB FPMSHLP VLAGGEN) - CR0, CR2, CR3 TH CR4. EUFSH Y DTHZYE (OBRTYNET, PFMBDPYUOSCHE TEZYUFTSHCH), OP POY OBU UEKYUBU OE YOFETEUKHAF. yNEOOP U RPNPESHA LFYI TEZYUFTCH RTPYJCHPDYFUS RETELMAYUEOYE RTPGEUUPTB H BEEYEIOOOSCHK TETSYN Y OBUFTPKLB OPCHSCHI ZHHOLGYK CHTPDE UFTBOYUOPK BDTEUBGYY. zing DPUFKHROSCH CH TEBMSHOPN TETSYNE.

h ЪBEEIЈOOPN TETSYNE RPOSFIE UEZNEOFB YЪNEOSEFUS. FERETSH FP OE RTPUFP VBPCHSHCHK BDTEU, B OPNET LMENEOFB (DEULTYRFPTB UEZNEOFB) CH UREGIBMSHOPK FBVMYGE. fBVMYGB DEULTYRFPTPCH UEZNEOPFCH UPDBЈFUS PRETBGYPOOPK UYUFENPK Y NPTCEF UPDETTSBFSH OEPVIPDYNPE LPMYUEUFCHP PRYUBOYK UEZNEOPPCH ЪBEYEIIOOPZP TETSYNB. LBCDShCHK LMENEOF FBVMYGSHCH BOINBEF 8 VBKF Y CH UREGIBMSHOPN ZHPTNBFE PRYUSCHCHBEF VBPCHSCHK BDTEU UEZNEOFB, TBNET, RTBCHB DPUFHRB Y F.D.

UEZNEOFSCH BEEIEIIOOPZP TETSYNB DEMSFUS OVER DCHB FIRB - UEZNEOFSC LPDB Y UEZNEOFSC DBOOSCHI (OVER UBNPN DEME EUFSH EEI CHUSLYE TSS Y LDT, OP RPLB SING OBNO OE CHBTSOSH FPTS). h CS NPTsOP ЪBZTHTSBFSH FPMSHLP OPNETB DEULTYRFPTPCH, PRYUBOOSHCHI LBL UEZNEOF LPDB, Ch PUFBMSHOSHCHE UEZNEOFOSHCHE TEZYUFTSH NPTsOP ЪBZTHTSBFSH MAVSHE UEZNEOFSHCH - LBL DBOOSCHI, FBL Y LPDBL. CHBTSOBS TBOYGB CH FPN, YuFP UEZNEOF LPDB NPTsOP FPMSHLP YUYFBFSH Y YURPMOSFSH, B UEZNEOF DBOOSCHI FPMSHLP YUYFBFSH Y RYUBFSH. L Uyubufsha, ueresenofsh NPZHF RETELTSHCHSHS CH RBNSFY, RPFPNH UPDSOPPSHE DELTRFPTB Dultirfptb, Ushchmbaeus over BOB FPF TEZIPO RBNSPHA, OPEI Oydbfsh yurpynchenshn.

oEUNPFTS OVER RPDDETZLH UEZNEOFBGYY, POB UYUYFBEFUS HUFBTECHYEK. oh Windows, oh Linux OE YURPMSHHAF EE H RPMOPC NO, B OB PFMYUOSCHI PF x86 BTIYFELFHTSHCH (OBRTYNET, ARM) PB WHAT FUHFUFFCHHEF. DMS TBZTBOYUEOIS DPUFHRB L RBNSFY YURPMSH'HEFUS ZPTBDDP VPMEE ZYVLYK NEIBOYN UFTBOYUOPK BDTEUBGYY, LPFPTSCHK NSC TBUUNPFTYN DBMEE. YuFPVSCH YUVBCHIFSHUS PF UEZNEOFBGYY PU RTPUFP PRIUSHCHBEF FBVMIGH YU DULTIRFPPCH, X LBCDPZP YH LPFPSHSHK BDTEU 0, B TBIPHK RBNSTEPHEPHEPHEPHP h FBLPN UMHYUBE ZPCHPTSF, YuFP NSCH CHLMAYUYMY TETSYN MYOEKOSHCHI BDTEUPCH - UNEEEOYE UPPFFCHEFUFCHHEF ZHYYYYUEULPNH BDTEUKH. FP PYUEOSH KDPVOP Y S RPKDH RP FPNKh CE RHFY. оЕ УМЕДХЕФ РЩФБФШУС ЙУРПМШЪПЧБФШ УЕЗНЕОФБГЙА Ч УЧПЕК ПРЕТБГЙПООПК УЙУФЕНЕ - ЬФП УЙМШОП ХУМПЦОСЕФ ЛПД СДТБ, СЪЩЛЙ ЧЩУПЛПЗП ХТПЧОС (ОБРТЙНЕТ, у ЙМЙ у++) ОЕ РПДДЕТЦЙЧБАФ УЕЗНЕОФБГЙА (ФП ЕУФШ ЧЩ УНПЦЕФЕ РПМОПГЕООП РТПЗТБННЙТПЧБФШ ФПМШЛП ОБ Assembler) Й, ОБЛПОЕГ, ЧЩ ОЕ УНПЦЕФЕ РЕТЕОЕУФЙ УЙУФЕНХ ОБ ДТХЗХА БТИЙФЕЛФХТХ, РПФПНХ ЮФП x86 ЕДЙОУФЧЕООБС, ЛПФПТБС ХНЕЕФ ЬФПФ НЕИБОЙЪН (Й ФП, Ч 64-ВЙФОПН ТЕЦЙНЕ РПМС ВБЪПЧПЗП БДТЕУБ Й ТБЪНЕТБ УЕЗНЕОФБ ЙЗОПТЙТХАФУС, Б ЙУРПМШЪХЕФУС МЙЫШ ЙОЖПТНБГЙС П РТБЧБИ ДПУФХРБ).

LBL S HCE ULBBM, FBVMYGB DEULTYRFPTPCH UEZNEOPHFCH ZHPTNYTHEFUS UBNPK PRETBGYPOOPK UYUFENPC. uFPVSC HLBBFSH RPGEUUPTH, ZDE POB OBIPDIFUS YURPMSHHEFUUS UREGYBMSHOBS LPNBODB - lgdt (Load Global Descriptor Table). POB RTYOYNBEF 6-VBKFPCHHA RETENEOOHA CH RBNSFY. рЕТЧЩЕ ЕЈ 16 ВЙФ УПДЕТЦБФ ТБЪНЕТ ФБВМЙГЩ Ч ВБКФБИ (ФБЛЙН ПВТБЪПН, НБЛУЙНБМШОПЕ ЛПМЙЮЕУФЧП ДЕУЛТЙРФПТПЧ - 65536 / 8 = 8192), РПУМЕДХАЭЙЕ 32 ВЙФБ - ВБЪПЧЩК МЙОЕКОЩК БДТЕУ Ч РБНСФЙ УБНПК ФБВМЙГЩ (ФП ЕУФШ ВЕЪ ХЮЈФБ ЧУЕИ УЕЗНЕОФПЧ). yNEEF UNSCHUM CHSHCHTBCHOSFSH OBYUBMP FBVMYGSHCH OB 16 VBKF, RPFPNKh YUFP LFP HMHYUYBEF ULTPUFSH DPUFHRB L EY EMENEOFBN. RETCHSHCHK LMENEOF FBVMYGSHCH CHUEZDB DPMTSEO VSHCHFSH TBCHEO OHMA Y MAVPE YURPMSHCHCHBOYE OHMECHPZP UEMELFPTB(HLBBFEMSH OVER MENEOF FBVMYGSCH DEULTYRFPTPCH CH UEZNEOFOPN TEZYUFTE OBSCCHCHBEFUS FBL) RTYCHPDYF L PYYVLE. OBYUYF VPMEE-NEOE TBVPFPPURPUPVOBS FBVMYGB DEULTYRFPTPCH DPMTSOB UPDETTSBFSH IPFS VSC FTY DEULTYRFPTTB - RHUFPK, DEULTYRFPT LPDB, DEULTYRFPT DBOOSCHI.

OH UFP EEJ UFPYF TBUULBЪBFSH, RTETSDE, YUEN NSCH RPRTPVKHEN RETEKFI CH ЪBEIEIIOOSCHK TETSYN? RPTsBMHK, EEI UFPYF HRPNSOHFSH RTP HTPCHOY DPUFHRB. LPD SDTB UYUFENSCH Y LPD RTYMPTSEOYK PFDEMEOSCH DTHZ PF DTHZB U FPK GEMSHHA, YuFPVSHCH SDTP NPZMP RPMOPUFSHA HRTBCHMSFSH RTPGEUUPTPN, B RTYMPTSEOIS OE NPZMY CHNEYBFSHUS H TBVPFH SDTB (CHEDSH HOB NOPYuPOS). LPD YURPMOSEFUS U PRTEDEMIOOSCHN HTPCHOYEN RTYCHYMEZYK. h x86 YI GEMSHI 4 YFKHLY - PF 0 DP 3. OHMECHPK HTPCHEOSH UBNSCHK RTYCHYMEZYTPCHBOOSCHK (NPCEF CHSHCHRPMOSFSH MAVSHE LPNBODSCH Y NEOSFSH TETSYNSCH TBVPFSCH RTPGEUUPTB), FTEFYK UBNSCHK "VEURTBCHOSCHK". LBB Comkhuba bij Uerezneoofbgyek, TBTBPFULY X86 RETEVPTAMYA bij Zholgypobmpn Yurpmshkhaf MYYSHA HTPCHOS YUEFSHTSHIEYA, BTIZYEEPHPHTHPHPHTHPHPHTHPHTHPHTHPHTBB FPPHEUUUUPTB FPPHEUUUUUPTBF FIPMENTB FPPHEUUUPTB FPPHEUUPTB FPPHEUUPTB FPPHBAPHBAPHBAPHBEPHBAPHBEPHABPHBE x LBTsDPZP UEZNEOFB CH EZP DEULTYRFPTE HLBBO DPL (Descriptor-privilegeniveau)- HTPCHEOSH DPUFHRB OEPVIPDYNSCHK DMS DBOOPZP UEZNEOFB. oERTYCHYMEZYTPCHBOOSCHK LPD OE NPTCEF RPMHYUYFSH DPUFHR L UEZNEOPH U HTPCHOYEN DPUFHRB 0, B RTYCHYMEZYTPCHBOOSCHK LPD NPTCEF RPMHYUYFSH DPUFHR LP CHUEN UEZNEOFBN.

уЕМЕЛФПТ УЕЗНЕОФБ, ЛПФПТЩК УПДЕТЦЙФУС Ч УЕЗНЕОФОПН ТЕЗЙУФТЕ, СЧМСЕФУС ОЕ РТПУФП ОПНЕТПН ЬМЕНЕОФБ Ч ФБВМЙГЕ, ОП Й ХЛБЪБФЕМЕН ХТПЧОС ДПУФХРБ - НМБДЫЙЕ 2 ВЙФБ УПДЕТЦБФ ХТПЧЕОШ РТЙЧЙМЕЗЙК (ПФ 0 ДП 3), Б ХЦЕ УФБТЫЙЕ ОПНЕТ УБНПК ФБВМЙГЩ. fBLYN PVBPN UEMELFPT = (YODELU_DEULTYRFPTB shl 2) + RPL. RPL- Gevraagd privilegeniveau - RTY LFPN RPL DPMCEO VSCFS VPMSHY YMY TBCHEO NBLUINBMSHOPNH Ъ DPL © CPL (huidig ​​bevoegdheidsniveau). CPL TBCHEO RPL UEMELFPTB H CS. fBLYN PVTBBPN LPD OE NPTCEF RPMKHYuYFSH DPUFHRB L UEZNEOFBN, H LPFPTSCHI HTPCHEOSH DPUFHRB CH YUYUMPCHPN CHYDE OYCE, YUEN X OEZP UBNPZP. s, CHETPSFOP, PRIUBM DPUFBFPYuOP BRHFBOOP, OP CHRPMOE NPTsOP PVPKFYUSH RPL = DPL, LBL NSCH en RPUFHRIN.

rPLB NSC RYYEN FPMSHLP SDTP, NSC VKHDEN TBVPFBFSH CH OKHMECHPN LPMShGE BEIFSHCH (FBL EEI OBSCCHBAF HTPCHOY RTYCHYMEZYK), YUFPVSH YNEFSH RPMOSHK DPUFHR L BRRBTBFKhTE.

UEZNEOFBGYS OBN O OHTSOB, RPFPNKH S OE VKHDH PUFBOBCHMYCHBFSHUS RPLB UFP OVER ZHPTNBFE DEULTYRFPTB, B DBN ZPFPCHSHCHE OBBYUEOYS. eUMY YOFETEUOP, NPTSEFE RPYUYFBFSH LFH UFBFSHHA. tBUUNPFTYN RTPUFEKYYK LPD RETEIPDB CH ЪBEYEIIOOSCHK TETSYN.

; bBRHUL 32-TBTSDOPZP SDTB.start32: ; WHCHCHPDYN HCHEDPNMEOYE P BRHULE 32-VYFOPZP SDTB mov si, start32_msg call write_str; bztkhjn bobyueoye h GDTR lgdt ; bBRTEFYN RTETSHCHCHBOYS cli ; RETEKDYN H BEEYEIIOOSCHK TEZYN mov eax, cr0 of eax, 1 mov cr0, eax ; RETEKDIN OVER 32-VYFOSHK LPD jmp 8: start32 ; fBVMYGB DEULTYRFPTPCH UEZNEOPFC DMS 32-VYFOPZP SDTB uitlijnen 16 gdt32: dq 0; NULL - 0 dq 0x00CF9A000000FFFF ; CODE - 8dq 0x00CF92000000FFFF; GEGEVENS - 16 gdtr32: dw $ - gdt32 - 1 dd gdt32 ; 32-VYFOSHK LPD gebruik32 start32: ; mov eax, 16 mov ds, axe moves, axe mov fs, axe mov gs, axe mov ss, axe movzx esp, sp ; WHCHCHPDYN UYNCHPM OVER LLTBO mov byte, "!" ; jmp $

FFPF LPD UMEDHEF DPRYUBFSH L

рЕТЕД РЕТЕИПДПН Ч ЪБЭЙЭЈООЩК ТЕЦЙН ОЕПВИПДЙНП ЪБРТЕФЙФШ РТЙЈН БРРБТБФОЩИ РТЕТЩЧБОЙК (ЛМБЧЙБФХТБ, НЩЫШ, ФБКНЕТ Й ДТХЗЙЕ ХУФТПКУФЧБ), РПФПНХ ЮФП BIOS РПУМЕ РЕТЕИПДБ ПУФБЈФУС ОЕ Х ДЕМ, Б УЧПЙ ПВТБВПФЮЙЛЙ НЩ ЕЭЈ ОЕ ОБРЙУБМЙ, РПЬФПНХ РЕТЧПЕ ЦЕ РТЕТЩЧБОЙЕ ПВТХЫЙФ УЙУФЕНХ.

oERPUTEDUFCHEOOP RETEIPD H ЪBEYEIIOOSCHK TETSIN PUKHEEUFCHMSEF HUFBOPCHLB OHMECHPZP VYFB CH CR0. yNEOOP LFP NSCH Y DEMBEN (RTSNPC DPUFKhR L CR0,2,3,4 OECHPЪNPTSEO FBL TSE LBL Y L UEZNEOFOSHCHN TEZYUFTBN, RPFPNKh YURPMSHEKHEN EAX). oEUNPFTS OB FP, UFP NSC HCE RETEYMY CH BEEIEIOOSHCHK TETSIN, LPD RTPDPMTSBEF YURPMOSFSHUS RP-RTETSOENH 16-VYFOSHCHK. dms dYTELFYCHB BUUENVMETB use32 ZPCHPTYF ENH, UFP DBMSHOEKYK LPD CHSHCHRPMOSEFUS CH ЪBEEIЈOOPN TETSYNE Y OEVPVIPDYNP RETELMAYUYFSHUS CH TETSYN ZEOETBGYY LPNBOD DMS OEZP, B OE 16-VYFOPHEMPZP (PO YUFOPZP)

lPNBODB movzx TBUYTSEF CHFPTPK BTZHNEOF DP RETCHPZP. h UNSHUME, YUFP YЪ 16 VYFOPZP OBBYUEOYS SP RPMHYUBEFUS 32-VYFOPE. uFBTYYE VYFSCH PVOHMSAFUS (NBMP MY, UFP FBN VSCHMP DP OBU). rTEDRPUMEDOSS LPNBODB DENPOUFTYTHEF OBN CHPЪNPTSOPUFY ЪBEYEIIOOPZP TETSYNB - NSC PVTBEBENUS RP BVUPMAFOPNKH 32-VYFOPPNKh BDTEUKH L CHYDEP-RBNSFY FELUFPPCHPZP TETSYNB, CHSHCHPPMS UYNHCHPDS "!" CH RTBCHSHCHK OYTSOYK HZPM LTBOB (FELUFPCHSCHK LTBO YNEEF TBTEYOYE 80 x 25 Uinchpmch, LBCDShCHK UINCHPM BOINBEF CH RBNSFY DCHB VBKFB - LPD UINCHPMB Y EZP BFTYVHFSHCH GCHEFB).

NSC VPMSHIE OE NPTSEN PVTBEBFSHUS L UETCHYUBN BIOS, FERETSH RTYYMP CHTENS OBN UFBFSH RPMOPUFSHHA UBNPUFPSFEMSHOSHCHNY Y UBNYN HRTBCHMSFSH CHUEN PVPTKHDPCHBOYEN. RETEBZTHTSBFSHUS Y TsDBFSH OBTSBFYS OVER LMBCHYYH NSC RPLB OE HNEEN, RPFPPNKh RTPUFP ЪBCHYUBEN U RPNPESHA LPNBODSCH jmp $ (RETEIPD OVER FX CE UBNHA LPNBODH - VEULPOEYUOSCHK GILM).

h COMMON boot.cfg LPNBODH S64 RPLB JBNEOIN OB S32. FERETSH, EUMY CHSHCHUY RTBCHYMSHOP UDEMBMY, OBY ЪBZTKHYUYL VKHDEF ЪBCHETYBFSH UCHPA TBVPFKH CHSHCHCHPDPN ChPULMYGBFEMSHOPZP ЪOBLB CH KhZPM LTBOB YЪ ЪBEYEIIOOPZP TETSYNB. FP FPMSHLP OBUBMP. NS OBLPOEG-FP RTBLFYUEULY KHYMYY YЪ TEBMSHOPZP TETSYNB (ON UBNPN DEME FBN EEI PUFBMPUSH OENPZP DEM) H BEEYEIIOOSCHK. Rpulpmshlh CHABZTHYUILEL CHCHRPMOSEFUS chMECHENEOFE TEBMshopzp Tekinb, Chueeoeeois Uppeffchhaf Zhyryotyipda Chuyoshchk Tsin, Oyuyuzp.

h ЪBCHETEOYE CHSHCHHRULB, RPTsBMHK, DPVBCHMA RPUMEDOYK YFTYI - RTPCHETLKH, UFP RTPGEUUPT RPDDETSYCHBEF ЪBEIEIIOOSCHK TETSYN. UHFSH RTPCHETLY CH FPN, UFP OE CHUE VYFSCH VLAGGEN NPTsOP YЪNEOYFSH RTPZTBNNOP. FP EUFSH TEZYUFT OE UPCHUEN 16-VYFOSHCHK. OVER OPCHSCHI RTPGEUUPTBI DPUFHROP DMS YNEOEOYS VPMSHIE VYF Y FP NPTsOP PVOBTHTSYFSH. TBVETYFE LPD OYCE UBNY, ULBTSH FPMSHLP, UFP LPNBODB pushf RPNEEBEF TEZYUFT ZHMBZPCH H UFEL, B popf CHCHFBMLYCHBEF UPDETSYNPE UFELP PE VLAGGEN. fBLYN PVTBYPN EZP NPTsOP NEOSFSH GEMILPN, BOE PFDEMSHOSHCHNY LPNBODBNY. CHPF RPMOSHCHK LPD OBYEZP ЪBZTKHYULB:

Org 0x7C00 jmp opstarten; bZPMCHPL LijstFS uitlijnen 4 fs_magic dd ? fs_versie dd? fs_flags dd ? fs_base dq? fs_size dq ? fs_map_base dq? fs_map_size dq? fs_first_file dq? fs_uid dq? fs_block_size dd ? ; bZPMCHPL JBKMB virtueel op 0x800 f_info: f_name rb 256 f_next dq ? f_vorige dq? f_parent dq? f_flags dq? f_data dq? f_size dq ? f_ctime dq? f_mtime dq? f_atime dq? eindvirtueel ; DBOOSH OBJUBMSHOPZP JBZTHYULB label sector_per_track woord op $$ label head_count byte op $$ + 2 label disk_id byte op $$ + 3 reboot_msg db "Druk op een toets...",13,10,0 boot_file_name db "boot.bin",0 ; hHCHPD UFTPLY DS:SI OB LTLBO write_str: push si mov ah, 0x0E @: lodsb test al, al jz @f int 0x10 jmp @b @: pop si ret ; lTYFYUEULBS PYVLB-fout: pop si call write_str; rete_bzthlb reboot: mov si, reboot_msg call write_str xor ah, ah int 0x16 jmp 0xFFFF:0 ; bZTHLB UELFPTB DX:AX H WCHET ES:DI load_sector: push dx add ax, word adc dx, word cmp byte, 0xFF je .use_EDD push bx cx si div mov cl, dl inc cl div mov dh, ah mov ch, al mov dl, mov bx, di mov al, 1 mov si, 3 @: mov ah, 2 int 0x13 jnc @f xor ah, ah int 0x13 dec si jnz @b .error: call error db "DISK ERROR",13,10 ,0 @: pop si cx bx dx ret .use_EDD: push si mov byte, 0x10 mov byte, 0 mov word, 1 mov , di push es pop word mov , axe mov , dx mov word, 0 mov word, 0 mov ah , 0x42 mov dl, mov si, 0x600 int 0x13 jc .error pop si dx ret ; rPYUL JBKMB U YNEOEN DS:SI H LBFBMPZE DX:AX find_file: push cx dx di .find: cmp ax, -1 jne @f cmp dx, -1 jne @f .not_found: call error db "NOT FOUND",13, 10,0 @: mov di, f_info call load_sector push di mov cx, 0xFFFF xor al, al repne scasb neg cx dec cx pop di push si repe cmpsb pop si je .found mov ax, word mov dx, word jmp .find . gevonden: pop di dx cx ret; ъBZTHЪLB FELHEEZP ZhBKMB Ch RBNSFSH RP BDTEUKh BX:0. lPMYUEEUFFCHP JBZTHCEOOOSCHI UELFPTPCH CHPCHTBEBEFUS H AX load_file_data: push bx cx dx si di mov ax, word mov dx, word .load_list: cmp ax, -1 jne @f cmp dx, -1 jne @f .file_end: pop di si dx cx mov ax, bx pop bx sub ax, bx shr ax, 9 - 4 ret @: mov di, 0x8000 / 16 call load_sector mov si, di mov cx, 512 / 8 - 1 .load_sector: lodsw mov dx, add si, 6 cmp ax, -1 jne @f cmp dx, -1 je .file_end @: push es mov es, bx xor di, di call load_sector add bx, 0x200 / 16 pop es loop .load_sector lodsw mov dx, jmp .load_list ; fPYULB CHIPDB CH OBYUBMSHOSHCHK ЪBZTHYUYL boot: ; oBUFTPYN WEZNEOFOSHCHE TEZYUFTSH jmp 0:@f @: mov ax, cs mov ds, ax mov es, ax ; oBUFTPYN UFEL mov ss, ax mov sp, $$ ; tbteyyn rtetschchchchboys sti ; bRPNOIN OPNET bZTHЪpyuopzp DYULB mov , dl ; mov ah, 0x41 mov bx, 0x55AA int 0x13 jc @f mov byte, 0xFF jmp .disk_detected @: mov ah, 0x08 xor di, di pushmoves int 0x13 pop es jc load_sector.error inc , dh cx, 111111b mov , cx . schijf_gedetecteerd: ; bZTHJIN RTPPMTSEOYE OBJUBMSHOPZP bZTKHJULB mov si, boot_file_name mov ax, word mov dx, word call find_file mov bx, 0x7E00 / 16 call load_file_data ; RETEIPDYN OVER RTPDPMCEOJE jmp boot2 ; rHUFPE RTPUFTBOUFCHP Y UYZOBFHTTB rb 510 - ($ - $$) db 0x55,0xAA ; dRPMYFEMSHOSHE DBOOSHE JBZTHYULB load_msg_preffix db "Bezig met laden "",0 load_msg_suffix db "". ..",0 ok_msg db "OK",13,10,0 config_file_name db "boot.cfg",0 start16_msg db "Start 16 bit kernel...",13,10,0 start32_msg db "Start 32 bit kernel. ..",13,10,0 ; tBVEOYE UFTPLY DS:SI RP UYNCHPMH UMEYB split_file_name: push si @: lodsb cmp al, "/" je @f test al, al jz @f jmp @b @: mov byte, 0 mov ax, si pop si ret ;bZTHJLB JBKMB U YNEOEN DS:SI N VHZET BX:0.tBNET JBKMB N UELFPTBI PPCHTBEBEFUS N AX load_file: push si mov si, load_msg_preffix call write_str pop si call write_str push si mov si, load_msg_s pop si push si bp mov dx, word mov axe, word @: push axe call split_file_name mov bp, axe pop axe call find_file test byte, 1 jz @f mov si, bp mov dx, word mov axe, word jmp @b @ : call load_file_data mov si, ok_msg call write_str pop bp si ret ; рТПДПМЦЕОЙЕ ОБЮБМШОПЗП ЪБЗТХЪЮЙЛБ boot2: ; ъБЗТХЪЙН ЛПОЖЙЗХТБГЙПООЩК ЖБКМ ЪБЗТХЪЮЙЛБ mov si, config_file_name mov bx, 0x1000 / 16 call load_file ; чЩРПМОЙН ЪБЗТХЪПЮОЩК ​​​​УЛТЙРФ mov bx, 0x9000 / 16 mov bp, 0x6000 mov dx, 0x1000 .parse_line: mov si, dx .parse_char: lodsb test al, al jz .config_end cmp al, 10 je .run_command cmp al, 13 je .run_command jmp .parse_char .run_command: mov byte, 0 xchg dx, si cmp byte, 0 je .parse_line ; rHUFBS UFTPLB cmp byte, "#" je .parse_line ; lPNNEOFBTYK cmp byte, "L" je .load_file ; bZTHJLB JBKMB cmp byte, "S" je .start ; bBRHUL SDTB; oEYCHEUFOBS LPNBODB mov al, mov [.cmd], al call error db "Unknown boot script command "" .cmd db ? db ""!",13,10,0 .config_end: ; rTY RTBCHYMSHOPN LPOZHYZHTBGYPOOPN ZHBKME NSC OE DPMTSOSCH UADB RPRBUFSH; jmp opnieuw opstarten; load_file: push dx inc si call load_file push axe mov cx, 512 mul cx mov word, axe mov word, dx mov word, 0 mov word, 0 mov axe, bx mov cx, 16 mul cx mov word, axe mov word, dx mov woord, 0 mov woord, 0 pop axe shr axe, 9 - 4 add bx, axe add bp, 16 pop dx jmp .parse_line ; bBRHUL SDTB.start: ; rTPCHETYN, UFP ЪBZTKhTSEO IPFS VSH PYO ZHBKM cmp bx, 0x9000 / 16 ja @f call error db "NO KERNEL LOADED",13,10,0 @: ; bBRPMOSEN RPUMEDOIK LMENEOF URYULB JBKMPCH xor axe, axe mov cx, 16 mov di, bp rep stosw ; RETEIPDYN L RTPGEDHTE YOYGYBMYYBGYY SDTB DMS OHTSOPK TBTSDOPUPY inc si cmp word, "16" je .start16 cmp word, "32" je .start32 ;cmp word, "64" ;je start64 ; oEYCHEUFOBS TSTSDOPUFSH SDTB-oproepfout db "Ongeldig startopdrachtargument",13,10,0; bBRHUL 16-TBTSDOPZP SDTB.start16: mov si, start16_msg mov bx, 0x6000 mov dl, jmp 0x9000; bBRHUL 32-TBTSDOPZP SDTB.start32: ; WHCHCHPDYN HCHEDPNMEOYE P BRHULE 32-VYFOPZP SDTB mov si, start32_msg call write_str; rTPCHETYN, UFP RTPGEUUPT OE IHCE i386 mov axe, 0x7202 push axe popf pushf pop bx cmp axe, bx je @f call error db "Vereiste i386 of beter",13,10,0 @: ; bztkhjn bobyueoye h GDTR lgdt ; bBRTEFYN RTETSHCHCHBOYS cli ; RETEKDYN H BEEYEIIOOSCHK TEZYN mov eax, cr0 of eax, 1 mov cr0, eax ; RETEKDIN OVER 32-VYFOSHK LPD jmp 8: start32 ; fBVMYGB DEULTYRFPTPCH UEZNEOPFC DMS 32-VYFOPZP SDTB uitlijnen 16 gdt32: dq 0; NULL - 0 dq 0x00CF9A000000FFFF ; CODE - 8dq 0x00CF92000000FFFF; GEGEVENS - 16 gdtr32: dw $ - gdt32 - 1 dd gdt32 ; 32-VYFOSHK LPD gebruik32 start32: ; mov eax, 16 mov ds, axe moves, axe mov fs, axe mov gs, axe mov ss, axe movzx esp, sp ; WHCHCHPDYN UYNCHPM OVER LLTBO mov byte, "! "; 'VIER' jmp $

Om een ​​besturingssysteem te schrijven, moet u veel details begrijpen. Hier, laat me je een beetje informeren (maar laten we afspreken dat je de mana zelf zult lezen, zodat er iets is om over te praten).
Om eerlijk te zijn, er is veel PM-materiaal op het net, en iley en pehat hebben wat over deze modus gepraat, maar ik werd toch gevraagd om het in algemene termen te beschrijven. Nu zal ik kort een theorie geven (eigenlijk heeft Intel speciaal hiervoor mana geschreven), daarna gaan we code schrijven.

Inleiding tot de beveiligde modus.
PM is dus aanzienlijk anders dan alles wat bekend is sinds DOS een echte modus (RM) is. Nu moet je eraan wennen: er zijn geen statische, 64 kilobyte segmenten, interrupttabellen in 1 kilobyte, segmentbasisadressen in segmentregisters, over het algemeen een compleet nieuwe wereld.
De segmenten worden nu beschreven in Globale descriptortabel (GDT). Deze tabel kan maar in één exemplaar zijn. Ze is een structuur in het geheugen. Geen segment! Het kan zich overal in het geheugen bevinden, maar het adres en de limiet worden naar het GDTR-register geschreven. Hier is de structuur:

De tabel zelf bestaat uit ingangen met de volgende structuur (trouwens, de null-ingang is leeg. Dit is belangrijk. Als u toegang krijgt tot geheugen dat wordt 'beschreven' door een null-descriptor, krijgt u #GP - General Protection Fault):
Laten we deze structuur eens nader bekijken.

1. Segmentlimiet:
Het doel van dit veld is duidelijk uit de naam, maar er is een subtiliteit. De hond is begraven in het G (Granularity) bit.
Als deze niet is ingesteld, wordt het geheugen 'geteld' in bytes. In dat geval kan de segmentgrootte variëren van 1 byte tot 1 megabyte per 1 byte.
Als we het op 1 zetten, wordt geheugenpaging geïntroduceerd. Dan kunnen we van 4 kilobytes naar 4 gigabyte RAM adresseren met een formaatwijziging van 4 kilobytes (paginagrootte). In het algemeen verdient pagina-adressering de voorkeur (vergelijk (1Mb+64Kb-16byte) en 4Gb). Laten we het alleen hebben over segmentadressering in dit bericht. Paging verdient een aparte discussie.

2. Basisadres:
Hier specificeren we het fysieke adres van de basis.

3. Typeveld:
Bitcombinaties bepalen het segmenttype:

4. S (descriptortype):
De Intel-documentatie zegt dat als dit bit niet is ingesteld, deze descriptor voor het systeemsegment is, anders - code of data. Systeem betekent LDT, TSS, Interrupt Gates en dergelijke (later meer hierover).

5. DPL (Descriptor Privilege Level):
Rechten van het beschreven segment. Iedereen kent ringen.

6. P (segment aanwezig):
Als dit bit is ingesteld, 'weet' de processor dat het segment al in het geheugen zit (hoewel het beter is om geldig te zeggen). Als u een descriptorkiezer laadt waarvan de P-bit niet is ingesteld in het segmentregister, treedt een #NP-uitzondering (niet aanwezig) op. Over het algemeen zal de betekenis van deze sierlijke uitdrukking iets later worden uitgelegd.

7.D/B:
Voor segmenten van verschillende typen wordt het anders geïnterpreteerd.
1. Voor codesegmenten:
32 of 16 bit effectieve adreslengte en operandlengte.
(1-32; 0-16);
2. Voor stapel:
De stapelwijzer is 32 of 16 bits. (1-32; 0-16);

8.G:
Beïnvloedt in welke eenheden (bytes, pagina's) de segmentlimiet wordt gemeten. Over het algemeen kan paging worden ingeschakeld bij het invoeren van PM door bit 31 van het CR0-register in te stellen.

Wat meer informatie:
We vermoeden dat het woord Global niet voor niets is gebruikt. Er is dus nog een teken. Toegegeven, die is er ook Lokale descriptortabel. Het kunnen er heel veel zijn. Ze kunnen bijvoorbeeld worden gebruikt bij de uitvoering van taken, enz. En hier LDT vertegenwoordigt al een segment! Dus wen aan zinnen als 'lokale descriptor tabelsegmentdescriptor'.

Nadat we de tabel hebben beschreven, moeten we deze in het register laden AVG. Dit gebeurt verre van bewegen. AVG ingevuld door het team lgdt forwoord (waarde). Dat wil zeggen, het is noodzakelijk om deze structuur zelf te vormen en in het bovengenoemde register te laden. Er zijn nog steeds teams die met dit register werken, maar we galopperen door Europa.

Nog even. In PM slaan segmentregisters niet de basisadressen van segmenten op (zoals in RM), maar worden speciaal getrainde stukken genoemd selectors. Hun structuur is:

Hier is Index het volgnummer van de descriptor in de tabel.
TI laat zien waar de descriptor moet worden gezocht (in GDT of LDT).

Nu het al duidelijk is hoe je een tabel moet bouwen, laten we het hebben over hoe je naar PM kunt overschakelen (ik merk op dat dit alleen vanuit RM kan worden gedaan). Over het algemeen... hoef je alleen bit 0 van het besturingsregister CR0 in te stellen. Hoewel ik lieg. Eerst moet je alle interrupts uitschakelen ( NMI (Niet-maskeerbare onderbrekingen) inclusief), open adresregel A20(zodat 32-bits adressering beschikbaar is), downloaden AVG, en spring naar de markering - start.

Laten we een loader gebruiken (je kunt KOLIBRI's nemen), die onze code zal laden op het adres 1000h: 0 (RM's, ik merk op, het adres).
Hier zal alles niet zo soepel verlopen als in die manas, wanneer ze rechtstreeks vanuit de bootloader naar PM overschakelen. Alles is een beetje ingewikkelder. Maar laten we eerst eens kijken naar de code die de bootloader zal laden (we schrijven alles in FASM "e). Dit is een soort hallowereld. Laten we opstarten, naar PM gaan en een begroeting afdrukken. Dat is alles.

formaat binair
xorax, bijl
cli ; segmentregisters opnieuw initialiseren
mov ss, bijl
xorsp,sp
zo
movax, 3
int 10u

Jmp 1000u:r_start

Mov ax, 1000h; registers opnieuw configureren
mov ds, bijl
beweegt, bijl

In al, 0x92; schakel A20 in
of al, 2
uit 0x92,al

Lgdt forword ;laad GDTR-register
verplaats eax,cr0
of al,1;stel bit 0 in
mov cr0,eax;zet PM aan

Jmp voorwoord 08h:Startup32; ga naar PB

Uitlijnen 8 ; processor verwerkt uitgelijnde plaat sneller
BTW:
dq 0 ;leeg
db 0FFh,0FFh,0,0,0,9Ah,0CFh,0 ;code
db 0FFh,0FFh,0,0,0,92h,0CFh,0;gegevens
db 0FFh,0FFh,0,80h,0Bh,92h,40h,0 videosegment
label GDT_SIZE op $-GDT
AVG:
dw GDT_SIZE-1
ddGDT+10000u
; u moet een 32-bits adres schrijven. Nu zijn we in segment 1000h, waarvan de basis 1000h*10h is (door; fysiek adres) => fysiek adres van GDTR (labels!) = 10000h (fysiek adres van segmentbasis)+offset

Virtueel ; nu vullen we in feite de ruimte tot het einde van het segment
rb 10000 uur-$;
einde virtueel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;PM32-invoer;;;;;;;;;;;;;;; ;; ;;
gebruik32
org $+10000h; hier is wat: in PM werken we met Flat-segmenten, en als we de code laten; voor PM vóór org, dan zal het intra-segmentadres niet overeenkomen met het Flat-adres. Dus.

Startup32: ;PM ingangspunt
mov axe,10h ;schuif hier de keuzeschakelaars. Vaak (! vergeet het serienummer niet in
mov es,ax ;table) codesegmentkiezer - 08h. gegevens - 10 uur, videosegment - 18 uur
mov ds, bijl
mov fs, bijl
mov ss, bijl
mov esp,10000h;stapel
movax, 18u
mov gs, bijl

Mov esi,hi_string ;laat zien dat we geslaagd zijn
bel afdrukken
jmp $

;ESI - tekenreeksadres
afdrukken:
pushad
xor ebx, ebx
mov ah,07h;attribuut
zet:
beweeg al,
beweeg, bijl
incl. ebx
test al, al
jnz zet
popad
ret
hi_string db ‘Welkom bij PM, gast’,0

Wat hebben we gedaan? De lader heeft ons met succes geladen om 1000 uur: 0, vanwaar we de uitvoering voortzetten. Eerst ingeschakeld A20, alle interrupts uitgeschakeld, geladen in AVG juiste waarde, naar het invoerlabel gesprongen. Ik constateer dat we door zijn gesprongen
jmp voorwoord 08h:Startup32
Dwz 08h - code descriptor selector. Wen er aan.

Nu hoe dit wonder te beginnen. Persoonlijk gebruik ik WinImage en VirtualBox. We duwen de bootloader in de floppy-bootsector en plaatsen het .bin-bestand in de root. We slaan het op in .vfd, schrijven het pad naar de floppy-image in de eigenschappen van de virtuele machine, voeren het uit en zien het resultaat.

In het volgende nummer zullen we kijken naar interrupts, errors, traps, aborts en hoe ze werken, worden opgevangen en gedebugd. Laten we beginnen met praten over architectuur.

Informatie bronnen.
1) Ik wil alleen maar mijn dankbaarheid uiten aan Phantom_84 aka ego's voor het tonen van het juiste pad en het helpen vanaf het allereerste begin. Zonder hem zou het voor mij veel moeilijker zijn om erachter te komen.

Alle verwerkers Intel, beginnend met i80286 en tot de nieuwste, werken bij het opstarten (na de eerste "reset") in real-adresmodus (real-modus). Gewoonlijk wordt de real-modus gebruikt als tussenproduct voor het overschakelen naar de beschermde modus na de initialisatie van het microprocessorsysteem, of voor een snellere uitvoering van programma's die voor microprocessors zijn geschreven. 8086 , 80186 , maar vergeleken met 8086 , 80186 hebben moderne microprocessors in real-modus een bredere set uitvoerbare instructies en de mogelijkheid om 32-bits operanden te verwerken.
Het overschakelen van de processor naar de beschermde modus vanuit de echte modus wordt gedaan door op te starten CR0(Fig. 1) woorden met een enkele waarde van de PE-bit ( Bescherm Inschakelen). Voor compatibiliteit met software voor 80286 kan de PE-bit ook worden ingesteld door de LMSW-instructie. Voordat u het geheugen inschakelt, moeten de benodigde descriptortabellen worden geïnitialiseerd IDT En GDT. Onmiddellijk na het inschakelen van de beveiligde modus heeft de processor CPL = 0.

Rijst. 1

Voor alle 32-bits processors wordt de volgende reeks stappen aanbevolen om over te schakelen naar de beveiligde modus:
1. Schakel maskeerbare interrupts uit door de IF-vlag te resetten en blokkeer het optreden van niet-maskeerbare interrupts door externe logica.De programmacode moet tijdens de "overgangsperiode" de afwezigheid van uitzonderingen garanderen en geen software-interrupts gebruiken. Deze vereiste wordt veroorzaakt door een wijziging in het mechanisme voor het aanroepen van interrupthandlers.
2. Uploaden naar AVG basis adres GDT(volgens LGDT-instructie).
3. Instructie MOV KRO stel de PE-vlag in en als wisselgeheugen vereist is, dan de PG-vlag.
4. Onmiddellijk daarna wordt het commando voor springen tussen segmenten ( JMP Ver) of bel ( BEL ver) om de wachtrij met real-mode gedecodeerde instructies te wissen en CPU-serialisatie uit te voeren. Als paging is ingeschakeld, dan zijn de instructiecodes MOV KRO En JMP of TELEFOONGESPREK moet op een pagina staan ​​waarvan het fysieke adres overeenkomt met het logische adres (voor de code waarnaar de besturing wordt overgedragen, wordt deze vereiste niet opgelegd).
5. Als u van plan bent een lokale descriptortabel te gebruiken, is de instruction LLDT lastsegmentkiezer voor LDT registreren LDTR
6. Instructie LTR laden in taakregisterkiezer TSS voor de initiële taak in de beveiligde modus.
7. Herlaad segmentregisters (behalve CS), waarvan de inhoud nog steeds tot de real-modus behoort, of voer een overgang uit of roep een andere taak aan (in dit geval worden de registers automatisch opnieuw geladen). Ongebruikte segmentregisters worden geladen met selector nul.
8. Instructie LIDT uploaden om te registreren IDTR adres en limiet IDT- descriptortabellen in de beschermde modus.
9. Sta maskeerbare en niet-maskeerbare hardware-interrupts toe

Dit artikel geeft enige inleiding tot de ontwikkeling van programma's die werken in de beschermde modus van de processor. Hier worden de hoofdtaken van elk programma dat in de beveiligde modus werkt, ingesteld en worden hun oplossingen gegeven. In principe worden de programma's in de taal geschreven FASM.

Bedrijfsmodi van de Intel 80386-processor

Met de komst van de processor Intel 80386 architectuur ontstond IA32. Het ging uit van de opkomst van een nieuwe werkingsmodus van de processor - beschermd (" Beveiligde modus"). Voor compatibiliteit met eerdere processors in de lijn Intel 80x86 CPU 80386 startte niet meteen in de beschermde modus, maar werkte in de zogenaamde echte modus (" Echte modus"). Bovendien heeft elke modus een of meer submodi. Laten we ze analyseren.

echte modus

In deze modus is de processor direct na het indrukken van de " stroom"computer. Real-mode geheugen is ontworpen" segment: offset", dat het logische adres beschrijft. De segmentwaarde varieert, net als de offset, van 0 voor 0FFFFh.

Aangezien u slechts binnen één segment kunt adresseren, is de maximale segmentgrootte 64 kilobyte. Het fysieke adres dat is ingesteld op de adresbus van de processor wordt berekend met de formule:

lineair adres = segment * 16 + offset

Real-modus processors 80186 En 8086 segmentwaarde varieerde van 0 voor 0F000u. Het maximaal blootgestelde adres op de adresbus is dus 0FFFFFh, wat overeenkomt (2^20)-1 , d.w.z. 1 megabyte.

In eerste instantie leek de hoeveelheid geheugen natuurlijk enorm, maar na verloop van tijd was één megabyte niet genoeg. Met de komst van de processor 80286 het zogenaamde geheugenblok kwam beschikbaar UMB, beginnend met adres 0FFFFu:0010u en eindigend met het adres 0FFFFh:0FFFFh(65520 bytes voorbij één megabyte). Nu was het mogelijk om het besturingssysteem opnieuw te configureren MS-DOS zodat het dit blok bezet, waardoor 64 kilobytes aan RAM vrijkomt.

Beveiligde modus

Deze modus heeft een complexe structuur in vergelijking met de echte. Het logische adres wordt weergegeven door de constructie " keuzeschakelaar: offset". De selector staat tussen 0 voor 0FFFFh(in feite zijn er 4 keer minder selectors - meer hierover in de volgende artikelen). De offset is, in tegenstelling tot de echte modus, 32-bits, waardoor segmenten van 4 gigabyte kunnen worden geadresseerd. Het logische adres wordt omgezet naar een lineair adres volgens het volgende schema:

lineair adres = segmentbasis + offset

Het lineaire adres wordt dan ingesteld op de adresbus, tenzij de pagingmodus is ingeschakeld. Anders wordt het lineaire adres geconverteerd naar een fysiek adres en pas daarna wordt het ingesteld op de adresbus. Bovendien kunt u met de beveiligde modus virtueel geheugen organiseren, met een grootte van maximaal 64 terabytes en alleen afhankelijk van de grootte van de harde schijf (bijvoorbeeld hetzelfde wisselbestand in ramen implementeert virtueel geheugen). Bijna alle moderne besturingssystemen werken in de beveiligde modus.

Multitasking Beschermde modus Submodus

Met deze modus kunt u multitasking organiseren, dat wil zeggen de mogelijkheid om tegelijkertijd meerdere taken of een systeem voor meerdere gebruikers uit te voeren.

Virtuele 8086-modus

Het is ook een submodus van de beveiligde modus waarmee u een virtuele machine kunt maken die functioneert alsof deze zich in de echte modus bevindt, maar in werkelijkheid in de beveiligde modus draait.

Onwerkelijke modus

Dit is een speciale submodus van de echte modus. De processor staat in real-modus, maar adresseert geheugen door " keuzeschakelaar: offset". Er is dus geheugen van meer dan 1 megabyte beschikbaar. In de toekomst zullen de beveiligde modus en zijn submodi worden overwogen.

Eerste programma: overschakelen naar beschermde modus

Overschakelen naar de beschermde modus gebeurt door het instellen van de bit 0 register CR0. De overgang naar de reële modus wordt uitgevoerd door hetzelfde nulbit te resetten. Beschouw een programma dat deze bewerking uitvoert (taal - Platte monteur):

gebruik16 ; Er worden 16-bits instructies gebruikt

org 100 uur

begin:

; We zijn in realtime

verplaats ex, cr0 ; Lees de waarde van register CR0
of al, 1 ; Stel nul bit in
verplaats cr0,eax ; Schrijf een nieuwe waarde naar CR0

; We zijn in de beveiligde modus

verplaats ex, cr0 ; De waarde van CR0 lezen
En al, 0feh ; Nulbit resetten naar 0
verplaats cr0,eax ; Overschakelen naar echte modus

; We zijn in realtime

ret ; Het programma verlaten

Dit programma is echter nogal "onbewerkt" omdat looping er niet in kan worden geïmplementeerd. Als je commando's schrijft zoals ht of jmp $, en wanneer de eerste interrupt wordt geactiveerd, wordt de computer opnieuw opgestart.

In ons geval werken de commando's vrij snel, maar het is mogelijk dat in het interval tussen de uitvoering van commando's van ons programma de interrupt nog steeds werkt, wat zal leiden tot een onmiddellijke crash en opnieuw opstarten. Zorg daarom voor onderbrekingen. Laten we dus nog eens naar de lijst kijken. Dit kan niet het eerste programma worden genoemd (het zou eerder voor nul gaan), aangezien het niet de belangrijkste acties implementeert om over te schakelen naar de beschermde modus. Om volledig over te schakelen naar de beveiligde modus met minimale instellingen, moet u de volgende stappen uitvoeren:

1. controleer of het mogelijk is om over te schakelen naar de beveiligde modus;

2. descriptortabellen initialiseren;

3. schakel interrupts uit (zowel maskeerbaar als niet-maskeerbaar);

4. open lijn A20;

5. geheugenbeheerregisters laden;

7. spring naar een 32-bits codesegment door het CS-register te negeren.

Maar het is voldoende dat het eerste programma stap 3, 4, 5 uitvoert. Dan zal de lus de computer niet opnieuw opstarten. Laten we elke stap eens bekijken.

Het uitschakelen van interrupts voorkomt dat we opnieuw opstarten. Interrupts zijn onderverdeeld in maskeerbaar en niet-maskeerbaar. Wis de vlag om maskeerbare onderbrekingen uit te schakelen ALS register EFLAGS team kli, terwijl interrupts worden ingeschakeld door de opdracht zo. Niet-maskeerbare interrupts worden op een iets andere manier uitgeschakeld. Er zijn twee manieren om dit te doen: het programmeren van de registers van de interruptcontroller (deze methode wordt later besproken) of het wijzigen van het zevende bit van de poort 70 uur: als de bit is ingesteld, zijn interrupts uitgeschakeld, als de bit vrij is, kunnen interrupts worden uitgevoerd.

Laten we ons nu afvragen wat de functie van de lijn is A20, Dus wat is dit. Lijn A20- een van de 32 adresregels. Wanneer de computer opstart, wordt de line A20 gesloten. Dit leidt tot het genereren van 20-bits adressen (dat wil zeggen, de volledige adresruimte is gelijk aan (2^20)=1 megabyte). Dit is geïntroduceerd voor compatibiliteit met de processor 8086 : dus proberen te schrijven naar een lineair adres 12345678 uur, schrijven we eigenlijk naar het adres 00045678u, wat kan leiden tot totaal onverwachte resultaten. Daarom is voor de volledige werking van een 32-bits applicatie de regel A20 moet geopend zijn. Dit wordt gedaan door het bit in te stellen 1 haven 92 uur, lijn sluiten A20- reset dit bit.

De lezer is al bekend met de laatste actie en zou hem geen vragen meer moeten stellen.

Laten we dus eens kijken naar de lijst van ons nieuwe, eerste programma, waarin al een kleine lus wordt geïmplementeerd. Rijen die aan de vorige lijst zijn toegevoegd, zijn gemarkeerd met een sterretje (*).

org 100 uur

begin:

; We zijn in realtime

kli ;*

in al, 70 uur ;*
of al, 80 uur ;*
uit 70 uur al ;*

; Open lijn A20

in al, 92 uur ;*
of al, 2 ;*
uit 92 uur, al ;*

verplaats ex, cr0
of al, 1
verplaats cr0,eax


; kleine dubbele cyclus

verplaats cx, 20 ;*

fiets: ;*
verplaats bijl, cx ;*
verplaats cx, 0ffffh ;*
lus $ ;*
verplaats cx, bijl ;*
lus fiets ;*

verplaats ex, cr0
En al, 0feh
verplaats cr0,eax

; Sluit lijn A20

in al, 92 uur ;*
En al, 0fdh ;*
uit 92 uur, al ;*

in al, 70 uur ;*
En al, 7fh ;*
uit 70 uur al ;*

zo ;*

ret ; maak het programma compleet

U kunt ervoor zorgen dat het programma werkt door het uitvoerbare bestand schoon uit te voeren MS-DOS. Als het programma correct eindigt, is alles in orde.

De volgende problemen kunnen echter ook optreden:

1. computer loopt vast";

2. de computer wordt opnieuw opgestart.

Dit kan om de volgende redenen gebeuren:

1. het programma loopt binnen V86(virtueel 8086 );

2. het programma wordt uitgevoerd in de beveiligde modus of onder een specifiek besturingssysteem.

Daarom moet u, voordat u een programma start dat in de beveiligde modus wordt uitgevoerd, de mogelijkheid van verder werk van het programma controleren. Dit zal verder worden besproken.

De mogelijkheid controleren om over te schakelen naar de beveiligde modus

In het vorige hoofdstuk hadden we het volgende probleem: het programma herkent niet dat het zich in de beveiligde modus bevindt of V86, waardoor het systeem vastloopt of opnieuw opstart. Als we proberen het programma onder het besturingssysteem uit te voeren ramen, Dat ramen zal de poging van het programma om over te schakelen naar de beveiligde modus opvangen en u vragen om opnieuw op te starten in de emulatiemodus MS-DOS(voor perron 9x), of het programma geforceerd beëindigen (platform NT).

Dus om te controleren of we echt in de echte modus zijn, moeten we de volgende bewerkingen uitvoeren:

1. controleer nul bit van register CR0;

2. zorg ervoor dat het Windows-besturingssysteem niet is geladen.

De eerste handeling wordt uitgevoerd door het register direct uit te lezen CR0 met verdere controle van het nulbit van het register EAX, BIJL of AL. Als de bit niet is ingesteld, bevinden we ons in de reële modus. Anders wordt verdere uitvoering van het programma zinloos.

De tweede actie wordt uitgevoerd door de functie aan te roepen 1600 uur onderbreekt 2fh. Met deze functie kunt u de huidige versie van het besturingssysteem ophalen ramen. Als na het aanroepen van de functie in het register AL nul bevat, is het besturingssysteem niet geladen. Anders is het wederom zinloos voor ons programma om verdere acties voort te zetten.

Beschouw het voorbeeld van het volgende programma. Het is een wijziging van het vorige programma, alle nieuwe instructies zijn gemarkeerd met een asterisk (*).

Org 100 uur

begin:

; Stel segmentregisters in

verplaats bijl, cs ;*
verplaats ds, bijl ;*

; Controleren of we echt in de echte modus zijn

verplaats ex, cr0 ;* nul-bitcontrole
test al, 1 ;* registreer CR0
jz geen_pm ;*

verplaats ah, 09h ;* DOS-functie 09h
verplaats dx, pm_msg ;* tekenreeksuitvoer
int 21u ;*
ret;* en ga naar buiten

geen_pm:
; Controleren of het programma onder Windows draait

verplaats bijl, 1600 uur ;* functie 1600h multiplexer
int 2fh ;* onderbreekt - download Windows-versie
test al, al ;* indien niet 0 - fout
jz geen_vensters

; Geef een foutmelding weer

verplaats ah, 09u ;*
verplaats dx, win_msg ;*
int 21u ;*
ret ;*

geen_vensters:
; We zijn zeker in realtime.
; Schakel maskeerbare interrupts uit

; Schakel niet-maskeerbare interrupts (NMI) uit

in al, 70 uur
of al, 80 uur
uit 70 uur al

; Open lijn A20

in al, 92 uur
of al, 2
uit 92 uur al

; Schakel over naar de beveiligde modus

verplaats ex, cr0
of al, 1
verplaats cr0,eax

; Nu zijn we in de beschermde modus
; kleine dubbele cyclus

verplaats cc, 20

fiets:
verplaats bijl, cx
verplaats cx, 0fffh
lus $
verplaats cx, bijl
lus fiets

; Schakel over naar de echte modus

verplaats ex, cr0
En al, 0feh
verplaats cr0,eax

; Sluit lijn A20

in al, 92 uur ;*
En al, 0fdh ;*
uit 92 uur, al ;*

; Schakel niet-maskeerbare interrupts (NMI) in

in al, 70 uur ;*
En al, 7fh ;*
uit 70 uur al ;*

; Schakel maskeerbare interrupts in

zo ;*

; We zijn terug in realtime

ret ; maak het programma compleet

; Foutmeldingen

pm_msg: ;*
db "Fout: draait al in beschermde modus!$" ;*
win_msg: ;*
db "Fout: Microsoft Windows gedetecteerd!$" ;*
Ook dit voorbeeld laat de implementatie van de 32-bits commando's nog niet zien. Om dit te doen, moet u zich ook vertrouwd maken met het materiaal van het volgende hoofdstuk. Daarnaast heeft het voorbeeld het volgende nadeel: de functies worden aangeroepen DOS (int 21u), wat al in tegenspraak is met de onafhankelijkheid van ons programma van het besturingssysteem MS-DOS. In de toekomst zult u moeten afzien van het gebruik van de functies van het besturingssysteem en verder moeten gaan met het gebruik van de functies BIOS. Maar voor nu is het voldoende om ons te beperken tot dergelijke code.

Ik speel momenteel met x86 Assembler om mijn programmeervaardigheden op laag niveau te verbeteren. Ik heb momenteel een klein probleem met het adresseringsschema in de 32-bits beveiligde modus.

De situatie is deze:

Ik heb een programma geladen op 0x7e0 dat de CPU in de beveiligde modus schakelt en naar het juiste label in de code springt:

[...] code om CPU in beveiligde modus te schakelen [...] jmp ProtectedMode [...] bits 32 ProtectedMode: .halt: hlt jmp .halt

Tot nu toe werkt alles geweldig. "Jmp ProtectedMode" werkt zonder een expliciete verre sprong om de prefetch-wachtrij leeg te maken, aangezien dit programma wordt geladen op offset 0 (org 0 aan het begin), waardoor het codesegment gedwongen wordt naar de juiste plaats te wijzen.

Mijn huidige probleem is dat ik in de snelkoppeling "ProtectedMode" naar een ander programma wil navigeren dat is geladen vanaf 0x8000 (ik heb dit gecontroleerd met een geheugendump, de laadfunctie werkte correct en het programma werd correct geladen tot 0x8000).

Omdat de CPU nu in ProtectedMode staat in plaats van RealMode, is het adresseringsschema anders. ProtectedMode gebruikt descriptors om het basisadres en de limiet in de descriptortabel op te zoeken om de gegeven offset toe te voegen en het fysieke adres te krijgen (zoals ik het begrijp). Daarom was het nodig om de GDT in te stellen voordat ProtectedMode werd geopend.

De mijne ziet er zo uit:

%ifndef __GDT_INC_INCLUDED__ %define __GDT_INC_INCLUDED__ ;*********************************** ;* Globale descriptortabel (GDT) * ; ******************************* NULL_DESC: dd 0; null-descriptor dd 0 CODE_DESC: dw 0xFFFF; grens laag dw 0 ; basis laag db 0 ; basis midden db 10011010b; toegang db 11001111b; granulariteit db 0 ; basis hoog DATA_DESC: dw 0xFFFF; gegevensbeschrijving dw 0 ; limiet laag db 0 ; basis lage db 10010010b; toegang db 11001111b; granulariteit db 0 ; basis hoog gdtr: Limiet dw 24; lengte van GDT Base dd NULL_DESC; basis van GDT %endif ;__GDT_INC_INCLUDED__

en in het GDT-register geladen via

lgdt

Wat ik nog steeds niet begrijp, is hoe verander ik nu naar fysiek adres 0x8000 in ProtectedMode met behulp van GDT?

Mijn eerste gedachten waren om een ​​codedescriptor (CODE_DESC) te kiezen die naar 0x7e00 zou moeten verwijzen (de huidige programma's zijn geladen) en de benodigde offset te gebruiken om 0x8000 (512 bytes) te krijgen, resulterend in een springcommando:

jmp CODE_DESC:0x200

Maar het werkt niet.

jmp 0x7e0:0x200

werkt ook niet...

Heb je enig idee wat ik hier mis? Misschien begreep ik iets belangrijks niet in het 32-bits ProtectedMode-adresseringsschema en het gebruik van GDT.

Volledige code:

Bits 16 org 0; geladen met offset 0000 (phys addr: 0x7e00) jmp Start Start: xor axe, axe mov axe, cs mov ds, axe; gegevenssegment cli bijwerken; wissen onderbreekt lgdt; laad GDT vanuit GDTR (zie gdt_32.inc) bel OpenA20Gate; open de A20-poortoproep EnablePMode; springt naar ProtectedMode ;****************** ;* Opent A20 Gate * ;****************** OpenA20Gate: in al, 0x93; switch A20 poort via snelle A20 poort 92 of al, 2; stel A20 Gate bit 1 en al, ~1 in; clear INIT_NOW bit out 0x92, al ret ;****************************** ;* Schakelt beveiligde modus in * ;**** **** ******************** EnablePMode: mov eax, cr0 of eax, 1 mov cr0, eax jmp ProtectedMode; dit werkt (springt naar label en stopt) ;jmp (CODE_DESC-NULL_DESC):ProtectedMode ; => werkt niet ;jmp 08h:ProtectedMode , => werkt niet ;*************** ;* gegevensvelden * ;* &includes * ;******** ****** %inclusief "gdt_32.inc" ;****************** ;* Beveiligde modus * ;*************** ******* bits 32 ProtectedMode: ; hier wil ik naar fysiek adres 0x8000 springen (elf64 asm-programma) .halt: hlt jmp .halt

11