इंटरनेट। कंप्यूटर। मदद करना। सलाह. मरम्मत

कंप्यूटर पर अपना खुद का ऑपरेटिंग सिस्टम कैसे बनाएं। एक सरल UNIX-जैसा OS बनाने के लिए एक मार्गदर्शिका। हमें क्या जरूरत है

रतिचेफुफ्चा चुई उचपी युफबफेमेक!

rTEDSDHEYE CHSHCHRKHULY NPZMY VSHCHFSH OEULPMSHLP ЪBRKhFBOOSCHNY। oBUBMSHOBS ЪБЗТХЛБ, असेंबलर, BIOS। UEZPDOS NSCH OBLPOEG RETEYIDYN L VPMEE YOFETEUOPK Y RPOSFOPK YUBUFY - NSCH OBUYOBEN RYUBFSH SDTP। वें RYUBFSH NSCH EZP VKhDEN SESSCHLE CHCHUPLPZP HTPCHOS y के बारे में।

h OBYUBMSHOSHK ЪBZTHYUYL PUFBMPUSH CHOEUFY CHUEZP RBTH DPRPMOEOYK Y PO VHDEF RPMOPUFSHA ZPFPCH ZTHYFSH MAVSCHCH 32-VYFOSCHE SDTB।

PRTEDEMEOYE PVAENB PRETBFYCHOPK RBNSFY

lPOYUOP, NPTsOP RPDUDUYFBFSH PVIAYN RBNSFY CHTHYUOHA CH SDTE - RETEVYTBFSH BDTEUB पीएफ 0x100000 Y RSHCHFBFSHUS ЪBRYUBFSH FKhDB OBYUEOYE PFMYYUOPE पीएफ OHMS Y 0xFF। ईयूएमवाई आरटीवाई युफियोय एनएससीएच आरपीएमख्यूबेन आरपीएमह्यूयूओपे ओब्युयॉय, एफपी चुएप आईपीटीपीवाईपी, योब्यू आरबीएनएसएफएसएच एलपीओयूयूएमबुश - Ъबीआरपीएनवाईओबेन बीडीटीईयू आरपीयूमेडोएजेडपी केएचडीबीयूओपीजेडपी यूफियोय्स, एलएफपी वाई वीएचडीईएफ पविएनएनपीएन प्रीटबीफाइचॉपक आरबीएनएसएफवाई। pDOBLP FBLPC UrPUPV YNEEF DCHB OEDPUFBFLB:

1) ईजेडपी उमेधेफ युरपम्सएचपीसीएचबीएफएसएच डीपी च्लमायुओयस उफ्टबॉययूओपीके बीडीटीईयूबीजीवाईवाई, युएफपीवीएसएच येनेफ्श डीपीयूएफएचआर एलपी चुएक झ्युयुल्पक आरबीएनएसएफवाई, एमवाईवीपी खुफ्टबिचबीएफएसएच ब्रियुश यूटे "पीएलओपी चेटेनियो" ओपीके यूएफटीबोइग्शच। माययोस एफटीबीएफबी चटनी, आरटीवाई हम्पची, यूएफपी फ्यूफाइटपचबॉय आरबीएनएसएफवाई बायोस वाई एफबीएल सीएचएसआरपीएमओएसईएफ आरटीई ओब्युबमशॉपक योयजीबीएमवाईबीजीवाईवाई, बी एनएससीएच डेम्बेन डीसीएचपीकोहा टीबीवीपीएफएच।

2). एल एफपीएनएच सीई बायोस रयेफ सीएच उब्न्हा पीवीएसयूओखा आरबीएनएसएफएसएच एफबीवीएमवाईजीएसएच एसीपीआई, एलपीएफपीटीएसएचई आरटीवाईजेडपीडीएसएफयूएस प्रीटबीजीपूपके उयुफेन वाई ओई यूएफपीवाईएफ यी Ъबीएफवाईटीबीएफएसएच डीपी आरटीपीयूफियोस।

हां एलएफपीपीजेडपी उमेधेफ, यूएफपी म्ह्युये उर्टपुयफश आरटीपी पव्याएन प्रीटबीफाइचॉप आरबीएनएसएफवाई एक्स बायोस, वीएमबीजेडपी ऑन आरटीईडीपीयूएफबीसीएचएमएसईएफ चुए ओईपीवीपीडीएनएससीएचई झखोलगी।

yUFPTYYUEULY RETCHPK JHOLGYEK PRTEDEMEOYS PVYANB PRETBFYCHOPK RBNSFY VSHMP RTETSCHCHBOIE 0x12। पॉप OE RTOYNBEF OILBLYI CHIPDOSCHI RBTBNEFTPCH, CH के बारे में CHSHCHIPDE CH TEZYUFTE AX UPDETSYFUS TBNET VBPCHPK RBNSFY CH LYMPVBKFBI। vББПЧБС RBNSFSH - FE UBNSCHE 640 lv DPUFHROSCHE CH TEBMSHOPN TETSINE। UEKYUBU CHSC HCE OE UNPTSEFE OBKFY LPNRSHAFET, ZDE VSH VSHMP NEOEE 640 LV RBNSFY, OP NBMP MY। yURPMSHЪPCHBFSH EЈ OBN UNSHUMB OEF - EUMY RTPGEUUPT RPDDETSYCHBEF BEEYEЈOOOSCHK TETSYN, FP CHTSD MY KH OEZP VkhDEF NEOSHYE OEULPMSHLYI NEZBVBKF RBNSFY।

pVyaЈNSCH RBNSFY TPUMY Y 640 lv UFBMP NBMP। fPZDB RPSCHYMBUSH OPCHBS ZHKHOLGYS - RTETSCHCHBOYE 0x15 AH=0x88। pOB CHP'CHTBEBEF CH AX TBNET TBUYYTEOOPK RBNSFY (छात्र 1 nv) CH LYMPVBKFBI CH AX। bFB Zholgys OE NPTSEF CHPCHTBEBFSH OBYUEOYS VPMSHYE 15 नवंबर (15 + 1 YFPZP 16 नवंबर)।

एलपीजेडडीबी वाई 16 एनवी यूवीबीएमपी ओईडीपीयूएफबीएफपीयूओपी आरपीएससीएचआईएमबुश ओपीसीएचबीएस झोलग्य्स - आरटीईटीएससीएचबीओईई 0x15, एएक्स=0xई801। POB CHPCHTBEBEF TEKHMSHFBFSCH BC CH 4 TEZYUFTBI:

AX - TBNET TBUYYTEOOOPK RBNSFY DP 16 nv Ch LYMPVBKFBI
BX - TBNET TBUYYTEOOOPK RBNSFY UCHETI 16 nv L VMPLBI RP 64 lv
CX - TBNET ULPOZHYZHTYTPCHBOOPC TBUYYTEOOPK RBNSFY DP 16 nv Ch LYMPVBKFBI
DX - TBNET ULPOZHYZHTYTPCHBOOPC TBUYYTEOOPK RBNSFY UCHETI 16 nv h VMPLBI RP 64 lv

YuFP FBLPE "ULPOZHYZHTYTPCHBOOBBS" RBNSFSH RTPYCHPDYFEMY BIOS UHDS RP CHUENKH OE DPZPCHPTYMYUSH, RPFPNKH OBDP RTPUFP, EUMY CH AX Y BX OHMY, VTBFSH OBYUE OYE CX Y DX।

ओपी वाई एलएफपीजेडपी पीएलबीबीबीएमपुश एनबीएमपी। चेद्श चुए रेटेयुउमेओओश चे झखोलग्य येनेफ पीजेडटीबॉययूओये पवेनेब आरबीएनएसएफवाई सीएच 4 स्टार, एल एफपीएनएच त्से ओई ख्यिफशचबाफ एफपी, यूएफपी आरबीएनएसएफएसएच एनपीटीएसईएफ वीएससीएफएस ओई ओर्टेटचचॉस्चन वीएमपीएलपीएन। rPFPNH CH OPCHSHHI BIOS RPSCHYMBUSH EEЈ PDOB Zholgys - RTETSCHCHBOIE 0x15, AX=0xE820। POB CHPCHTBEBEF OE RTPUFP YUYUMP, B LBTFH RBNSFY। चिपदोशे आरबीटीबीएनईएफटीएससीएच:

EAX=0xE820
EDX=0x534D4150 ("SMAP")
ईबीएक्स - यूनीईओये पीएफ ओयूबीएमबी एलबीटीएफएसएच आरबीएनएसएफवाई (डीएमएस ओयूबीएमबी 0)
ECX - TBNET VKHZHETB (LBL RTBCHYMP 24 VBKFB - TBNET PDOPZP BMENEOFB)
ES:DI - BDTEU VKHZHETB, LKhDB OBDP ЪBRYUBFSH PYUTEDOPK BMENEOF

chchipdosche RBTBNEFTSCH:

EAX=0x534D4150 ("SMAP")
ईबीएक्स - ओपीसीएचपीई यूनीओये डीएमएस उमेदहेइज़प सीएचएससीएचजेपीसीएचबी झखोलग्य्य। ईयूएमवाई 0, एफपी चुस एलबीटीएफबी आरबीएनएसएफवाई आरटीपीयूआईएफबीओबी
ECX - LPMYUEUFCHP TEBMSHOP CHPCHTBEYOOOSCHI VBKF (20 YMY 24 VBKFB)
एच खल्ब्बोपन व्हख्झेते अपडेट्सिफस प्युएटेडओपीके बीमेनियोफ एलबीटीएफएसएच आरबीएनएसएफवाई।

LBTSDSCHK BMENEOF LBTFSH RBNSFY YNEEF UMEDHAEHA UFTHLFHTH (OBRYYKH CH UYOFBLUIUE UI, RPFPNKH YuFP TBVPT DBOOSHI NSCH VKHDEN DEMBFSH HTSE CH SDTE):

संरचना ( अहस्ताक्षरित लंबा लंबा आधार; //vBBPCHSHCHK ZHYYYUEUULYK BDTEU TEZYPOB अहस्ताक्षरित लंबी लंबी लंबाई; //tBUNET TEZYPOB CH VBKFBI अहस्ताक्षरित लंबा प्रकार; // fYR TEZYPOB अहस्ताक्षरित लंबा acpi_attrs; //tBUYYTEOOSH BFTYVHFSCH ACPI );

rPUMEDOYK BMENEOF UFTKHLFKHTSCH OE PVSBFEMEO। ईईई सीएच पीडीओपीएन युफप्युओयले चाइडेम, यूएफपी सेवानिवृत्त ЪBRTPUPN BMENEOFB UFPYF RPNEUFYFSH FHDB EDYOYULH। lPOYUOP, UEKYUBU NSCHOE RPDDETSYCHBEN ACPI, OP MHYUYE ЪBTBOEE RPBBVPFYFUS P FPN, YUFPVSH RPMKHYUYFSH LBL NPTsOP VPMSHYE DBOOSCHI। एच PFMYYUYY पीएफ RBTBNEFTPCH RBNSFY, CHU PUFBMSHOP NPTsOP MEZLP KHOBFSH Y Y BEEYEЈOOOPZP TETSINB OBRTSNHA, VE BIOS।

तेजपोश आरबीएनएसएफवाई, प्र्युशचबेनशच एलबीटीएफपीसी, एनपीजेएचएफ वीएसएचचएफएसएच ओयूयूलपीएमश्ली एफवाईआरपीसीएच:

1 - पीवीएसएचयूओबीएस आरबीएनएसएफएसएच। nPTsEF VShchFSH UCHPVPDOP YURPMSHEPCHBOB PU DMS UCHPYI GEMEK। आरपीएलबी एनएससीएच एफपीएमएसएचएलपी एल ओके वाई वीकेडेन पीवीटीबीईबीएफएसएचयूएस, बी चुय पफबमशॉप आरटीपीआरखुलबफश।
2 - ъБТЭЧТПЧБОП (OBRTYNET, LPD BIOS)। bFB RBNSFSH NPTSEF VSCHFSH LBL ZHJYYUEULY OEDPUFHROB DMS ЪBRYUY, FBL Y RTPUFP ЪBRYUSH FHDB OETSEMBFEMSHOB। एफबीएलएचए आरबीएनएसएफएसएच म्युये ओई एफटीपीजेडबीएफएसएच।
3 - dPUFHROP RPUME RTPYUFEOOIS FBVMYG ACPI। चेटप्सफॉप, येनूओप सीएच FYI VMPLBI LFY FBVMYGSH Y ITBOSFUS। rPLB DTBKCHET ACPI OE RTPYUIFBEF FBVMYGSHCH, bFH RBNSFSH MHYUYE OE FTPZBFSH। rPFPN NPTsOP YURPMSHЪPCHBFSH FBL CE, LBL Y RBNSFSH FYRB 1।
4 - बीएफएच आरबीएनएसएफएसएच उमेधेफ उपिटबोसफश नेटएसडीएच एनवीएस यूयूयूआईएसएनवाई। एफबीएलएचए आरबीएनएसएफएसएच एनएससीएच एफटीपीजेडबीएफएसएच ओई वीखडेन, आरपीएलबी ओई खोबेन, यूएफपी एफबीएलपीई एनवीएस यूयूयूवाईवाई:-)

OE CHUE BIOS NPZHF RPDDETSYCHBFSH UFH ZHKHOLGYA। ईयूएमवाई एलबीएलबीएस-एफपी झोलग्य्स ओई आरपीडीडेट्साइचबेफस, एफपी आरटीवाई चशचिपदे ये ओईईएन खुफबोपचमेओ झमबज रेटरपमोयस वाई उमेधेफ प्राइवेटबीबीएफएसएचयूएस एल वीपीएमईई यूएफबीटीपीसी। nsch VKhDEN YURPMSHPCHBFSH ZHTNBF LBTFSH RBNSFY ZHKHOLGYY 0xE820। eUMY UBNH YFKH ZHOLGYA CHSHCHBFSH OE RPMKHYUMPUSH - RPMKHYUBFSH PVIAYN RBNSFY PVSHCHYUOSCHNY UTEDUFCHBNY Y UPJDBCHBFSH UCPA UPVUFCHEOKHA LBTFH RBNSFY Y PDOPZP FB। rPULPMSHLH PRTEDEMEOYE PVYaЈNB RBNSFY ЪBDББУБ ОХЦОБС ЪДС ЪБРХУЛБ 32-VYFOPZP ЪДС ЪБРХУЛБ 64-VYFOPZP SDTB, MHYUYE P ZhPTNYFSH EЈ CH Chyde RPDRTPZTBNNNSCH। एलबीटीएफकेएच आरबीएनएसएफवाई टीबीन्यूफिन आरपी बीडीटीईयूकेएच 0x7000। OE DKHNBA, YuFP POB NPTsEF VShchFSH VPMSHYE RBTSH LYMPVBKF। rPUMEDOYK BMENEOF CHTHYUOKHA UDEMBEN FYRB 0 - FBLPZP FYRB OE CHPTBEBEF BIOS Y LFP Y VHDEF RTYOBLPN LPOGB।

; rPMHYUEOYE LBTFSH RBNSFY get_memory_map: mov di, 0x7000 xor ebx, ebx @: mov eax, 0xE820 mov edx, 0x534D4150 mov ecx, 24 mov dword, 1 int 0x15 jc @f add di, 24 test ebx, ebx jnz @b @: सेमी पी di, 0x7000 ja .ok mov dword, 0x100000 mov dword, 0 mov dword, 0 mov dword, 1 mov dword, 0 mov ax, 0xE801 int 0x15 jnc @f mov ah, 0x88 int 0x15 jc .ok mov cx, ax xor dx , dx @: टेस्ट cx, cx jz @f mov ax, cx mov bx, dx @: movzx eax, ax movzx ebx, bx mov ecx, 1024 mul ecx पुश eax mov eax, ebx mov ecx, 65536 mul ecx पॉप edx जोड़ें eax, edx mov , eax add di, 24 jmp .ok .ok: xor ax, ax mov cx, 24/2 प्रतिनिधि Stosw ret

ओह सीएचपीएफ वाई जेडपीएफपीसीएच ओबीवाई ओबीयूबीएमशोशच ЪБЗТХЪУйЛ वीएचआई 32-वायफोशची एसडीईटी। एच BLMAYUEOYE RTYCHPTSKH EZP RPMOSHCHK एलपीडी वाई एनएससीएच रेटेकडेन एल एसडीटीएच।

; oYUBMSHOSHCHK ЪБЗТХЪУYЛ SDTB DMS BTIIFELFHTSCH x86 प्रारूप बाइनरी "बिन" org 0x7C00 jmp बूट के रूप में; ъБЗПМПЧПЛ ListFS 4 fs_magic dd संरेखित करें? एफएस_संस्करण डीडी? fs_flags dd ? fs_base dq ? fs_आकार dq ? fs_map_base dq ? fs_map_size dq ? fs_first_file dq ? fs_uid dq ? एफएस_ब्लॉक_साइज डीडी? ; ъБЗПМПЧПЛ ЖБКМБ वर्चुअल 0x800 f_info पर: f_name rb 256 f_next dq? f_prev dq ? f_parent dq ? f_flags dq ? f_data dq ? f_आकार dq ? f_ctime dq ? f_mtime dq ? f_atime dq ? अंत आभासी ; dBOOSHE OBYUBMSHOPZP ЪБЗТХЪУЛБ लेबल सेक्टर_पर_ट्रैक शब्द $$ पर लेबल हेड_काउंट बाइट $$ पर + 2 लेबल डिस्क_आईडी बाइट $$ पर + 3 रिबूट_एमएसजी डीबी "कोई भी कुंजी दबाएं...",13,10,0 बूट_फाइल_नाम डीबी "बूट.बिन",0 ; hCHCHPD UFTPLAY DS:SI BLTB के बारे में write_str: पुश si mov ah, 0x0E @: lodsb test al, al jz @f int 0x10 jmp @b @: पॉप si ret ; lTYFYUEULBS PYYVLB त्रुटि: पॉप si कॉल write_str ; RETEЪБЗТХЛБ रिबूट: mov si, रिबूट_msg कॉल राइट_str xor ah, ah int 0x16 jmp 0xFFFF:0 ; ъБЗТХЛБ UELFPTB DX:AX CH VHJET ES:DI लोड_सेक्टर: पुश डीएक्स ऐड एक्स, वर्ड एडीसी डीएक्स, वर्ड सीएमपी बाइट, 0xFF जेई .use_EDD पुश बीएक्स सीएक्स सी डिव मूव सीएल, डीएल इंक सीएल डिव मूव डीएच, एएच मूव सीएच, अल मूव 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: कॉल एरर db "डिस्क एरर",13,10 ,0 @: पॉप सीएक्स बीएक्स डीएक्स रेट .use_EDD: पुश सी मूव बाइट, 0x10 मूव बाइट, 0 मूव वर्ड, 1 मूव, डि पुश ईएस पॉप वर्ड मूव, एक्स मूव, डीएक्स मूव वर्ड, 0 मूव वर्ड, 0 मूव आह , 0x42 mov dl, mov si, 0x600 int 0x13 jc .error पॉप si dx ret ; rPYUL ZHBKMB U Yneoen DS:SI CH LBFBMPZE DX:AX find_file: पुश cx dx di .find: cmp ax, -1 jne @f cmp dx, -1 jne @f .not_found: कॉल एरर db "नहीं मिला",13, 10.0 @: mov di, f_info कॉल लोड_सेक्टर पुश di mov cx, 0xFFFF xor al, al repne scasb neg cx dec cx पॉप di पुश si repe cmpsb पॉप si .found mov ax, वर्ड mov dx, वर्ड jmp .find। पॉप डि डीएक्स सीएक्स रिट ; ъБЗТХЛБ FELHEEZP ZHBKMB CH RBNSFSH RP BDTEUKH BX:0. lPMYUEUFCHP ЪБЗТХЦЕОШИ UELFPTPCH CHPCHTBEBEFUS CH AX लोड_फ़ाइल_डेटा: पुश bx cx dx si di mov ax, वर्ड mov dx, वर्ड .load_list: cmp ax, -1 jne @f cmp dx, -1 jne @f .file_end: पॉप di si dx cx mov एक्स, बीएक्स पॉप बीएक्स सब एक्स, बीएक्स श्र एक्स, 9 - 4 रिट @: मूव डी, 0x8000 / 16 कॉल लोड_सेक्टर मूव सी, डी मूव सीएक्स, 512 / 8 - 1 .लोड_सेक्टर: लोड्सव मूव डीएक्स, ऐड सी, 6 सीएमपी ax, -1 jne @f cmp dx, -1 je .file_end @: पुश es mov es, bx xor di, di कॉल लोड_सेक्टर ऐड bx, 0x200 / 16 पॉप es लूप .load_sector lodsw mov dx, jmp .load_list ; fPULB CHIPDB CH OBYUBMSHOSHCHK ЪBZTHYUYL बूट: ; oBUFTPYN UEZNEOFOSHE TEZYUFTSH jmp 0:@f @: mov ax, cs mov ds, ax mov es, ax ; oBUFTPYN UFEL mov ss, ax mov sp, $$ ; TBTEYIN RTETSCHCHBOYS sti; ъBRPNOYN OPNET ЪБЗТХЪПУОПЗП ДИУЛБ mov, dl; prtedemyn RBTBNEFTSH ЪБЗТХЪПУОПЗП ДУЛБ mov ah, 0x41 mov bx, 0x55AA int 0x13 jc @f mov बाइट, 0xFF jmp .disk_detected @: mov ah, 0x08 xor di, di पुश es int 0x1 3 पॉप ईएस जेसी इंक डीएच मूव, डीएच और सीएक्स, 111111बी mov , cx .disk_detected: ; डाउनलोड करें डेटा; RTPDPMCEOYE jmp Boot2 के बारे में RETEIPDYN; rKHUFPE RTPUFTBOUFCHP Y UYZOBFKHTB आरबी 510 - ($ - $$) db 0x55.0xAA ; dPRPMOYFEMSHOSH DBOOSH ЪБЗТХЪУЛБ लोड_msg_preffix db "लोड हो रहा है "",0 लोड_msg_suffix db ""। ..",0 ok_msg db "OK",13,10,0 config_file_name db "boot.cfg",0start16_msg db "16 बिट कर्नेल प्रारंभ हो रहा है...",13,10,0 प्रारंभ32_msg db "32 बिट कर्नेल प्रारंभ हो रहा है। ..",13,10,0 लेबल मॉड्यूल_सूची 0x6000 पर लेबल मेमोरी_मैप 0x7000 पर; @बी @: मूव बाइट, 0 मूव एएक्स, सी पॉप सी रेट; पुश सी मूव सी, लोड_एमएसजी_सफिक्स कॉल राइट_स्ट्र पॉप सी पुश सी बीपी मूव डीएक्स, वर्ड मूव एक्स, वर्ड @: पुश एक्स कॉल स्प्लिट_फाइल_नाम एमओवी बीपी, एक्स पॉप एक्स कॉल फाइंड_फाइल टेस्ट बाइट, 1 जेजेड @एफ मूव सी, बीपी मूव डीएक्स, वर्ड मूव एक्स, वर्ड जेएमपी @बी @: कॉल लोड_फाइल_डेटा मूव सी, ओके_एमएसजी कॉल राइट_स्ट्र पॉप बीपी सी रिट; mov dword, 0 mov ax, 0xE801 int 0x15 jnc @f mov ah, 0x88 int 0x15 jc .ok mov cx, ax xor dx, dx @: test cx, cx jz @f mov ax, cx mov bx, dx @: movzx eax, ax movzx ebx, bx mov ecx, 1024 mul ecx पुश eax mov eax, ebx mov ecx, 65536 mul ecx पॉप edx add eax, edx mov, eax add di, 24 jmp .ok .ok .ok: xor ax, ax mov cx , 24 / 2 प्रतिनिधि स्टोस्व रेट ; rTPDPMTSEOYE OBUBMSHOPZP ЪБЗТХЪУЛБ बूट2: ; ъБЗТХЪН ЛПОжІЗХТБГИПООСЧК ЖБКМ ЪБЗТХЪУЛБ mov si, config_file_name mov bx, 0x1000 / 16 कॉल लोड_फ़ाइल ; CHSPMOYN ЪБЗТХПУОШК ULTYRF mov bx, 0x9000 / 16 mov bp, मॉड्यूल_लिस्ट 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, 1 3 जेई .रन_कमांड जेएमपी .parse_char .run_command: mov बाइट, 0 xchg dx, si cmp बाइट, 0 je .parse_line ; आरएचयूएफबीएस यूएफटीपीएलबी सीएमपी बाइट, "#" जेई .parse_line ; lPNNEOFBTYK सीएमपी बाइट, "एल" जेई .load_file ; ъБЗТХЛБ ЖБКМБ सीएमपी बाइट, "एस" जेई .स्टार्ट; ъब्रहुल एसडीटीबी; oEYCHEUFOBS LPNBODB mov al, mov [.cmd], al कॉल त्रुटि db "अज्ञात बूट स्क्रिप्ट कमांड "" .cmd db ? db ""!",13,10,0 .config_end: ; आरटीवाई आरटीबीसीएचवाईएमएसएचओपीएन एलपीओजीएचटीबीजीवाईपीओओपीएन जेएचबीकेएमई एनएससीएच ओई डीपीएमटीएसओएससीएच यूएडीबी आरपीआरबीयूएफएसएच; जेएमपी रिबूट; ъБЗТХЛБ ЖБКМБ.load_file: पुश dx inc si कॉल लोड_फ़ाइल पुश ax mov cx, 512 mul cx mov वर्ड, ax mov वर्ड, dx mov वर्ड, 0 mov वर्ड, 0 mov ax, bx mov cx, 16 mul cx mov वर्ड, ax mov वर्ड, डीएक्स मूव वर्ड, 0 मूव वर्ड, 0 पॉप एक्स एसएचआर एक्स, 9 - 4 ऐड बीएक्स, एक्स ऐड बीपी, 16 पॉप डीएक्स जेएमपी .parse_line; ъBRHUL SDTB.प्रारंभ: ; rTPchetyn, YuFP ЪBZTHTSEO IPFS VSC PDIO ZhBKM cmp bx, 0x9000 / 16 ja @f कॉल त्रुटि db "कोई कर्नेल लोड नहीं हुआ", 13,10,0 @: ; ъBRPMOSEN RPUMEDOYK BMENEOF URYULB ZHBKMPCH xor ax, ax mov cx, 16 mov di, bp प्रतिनिधि Stosw ; रेटिपडिन एल आरटीपीजेडएचटीई योयजीबीएमवाईबीजीवाईवाई एसडीटीबी डीएमएस ओकेएचटीएसओपीके टीबीटीएसडीओपीयूएफवाई इंक सी सीएमपी शब्द, "16" जेई .स्टार्ट16 सीएमपी शब्द, "32" जेई .स्टार्ट32 ;सीएमपी वर्ड, "64" ;जे .स्टार्ट64 ; oEYCHEUFOBS TSTSDOPUFSH SDTB कॉल त्रुटि db "अमान्य प्रारंभ कमांड तर्क", 13,10,0; ъBRHUL 16-TBTSDOPZP SDTB.start16: mov si,start16_msg mov bx, मॉड्यूल_लिस्ट mov dl, jmp 0x9000; ъBRHUL 32-TBTSDOPZP SDTB.start32: ; CHHCHPDYN HCHEDPNMEOYE P ЪBRHULE 32-VYFOPZP SDTB mov si,start32_msg कॉल write_str ; rTPCHETYN, YuFP RTPGEUUPT OE IHTSE i386 mov ax, 0x7202 पुश ax पॉपफ पुशफ पॉप bx सीएमपी ax, bx je @f कॉल एरर db "आवश्यक i386 या बेहतर", 13,10,0 @: ; rPMKHYUN LBTFH RBNSFY कॉल get_memory_map ; pYYUFYN FBVMYGSH UFTBOYG xor ax, ax mov cx, 3*4096/2 mov di, 0x1000 प्रतिनिधि Stosw; ъBRPMOIN LBFBMPZ UFTBOIG mov वर्ड, 0x2000 + 111b mov वर्ड, 0x3000 + 111b ; ъBRPMOIN RETCHHA FBVMYGH UFTBOYG mov eax, 11b mov cx, 0x100000 / 4096 mov di, 0x2000 @: Stosd add eax, 0x1000 लूप @b; ъBRPMOYN RPUMEDOAA FBVMYGH UFTBOYG mov di, 0x3000 mov eax, dword या eax, 11b mov ecx, dword shr ecx, 12 @: Stosd add eax, 0x1000 लूप @b mov वर्ड, 0x4000 + 11b; कर्नेल स्टैक मूव वर्ड, 0x3000 + 11बी; कर्नेल पृष्ठ तालिका; ъБЗТХЪН ЪБУЕОЕЧ CR3 mov eax, 0x1000 mov cr3, eax ; ъБЗТХХЪН ЪБУУЭОЭ Ч GDTR lgdt ; ъBRTEFYN RTETSCHCHBOYS सीएलआई; रेटेकडेन सीएच BEEYEЈOOOSCHK TETSYN mov eax, cr0 या eax, 0x80000001 mov cr0, eax ; रीटेकडेन लगभग 32-वायफोशक एलपीडी जेएमपी 8:स्टार्ट32; fBVMYGB DEULTYRFPTPCH UEZNEOFPPCH DMS 32-VYFOPZP SDTB संरेखित 16 gdt32: dq 0; शून्य - 0 dq 0x00CF9A000000FFFF; कोड - 8 dq 0x00CF92000000FFFF; डेटा - 16 जीडीटीआर32: डीडब्ल्यू $ - जीडीटी32 - 1 डीडी जीडीटी32; 32-VYFOSHCHK LPD उपयोग32 प्रारंभ32: ; oBUFTPYN UEZNEOFOSH TEZYUFTSHY UFEL mov eax, 16 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov esp, 0xFFFFDFFC; rPNEUFYN CH DL OPNET ЪБЗТХЪПУОПЗП ДУЛБ mov dl, ; rPNEUFYN CH EBX BDTEU URYULB ЪБЗТХЦеOOШ itХБКМПЧ mov ebx, मॉड्यूल_लिस्ट; rPNEUFYN CH ESI BDTEU LBTFSH RBNSFY mov esi, मेमोरी_मैप; SDTP jmp 0xFFC00000 के बारे में RETEIPDYN

रीचपे एसडीटीपी

एसडीटीपी आरपीएलबी केएच ओबीयू वीकेएचडीईएफ यूपीयूएफपीएसएफएसएच वाईजे डीसीएचएचआई जेएचबीकेएमपीसीएच - स्टार्टअप.एएसएम वाई मेन.सी. स्टार्टअप.asm OHTSEO DMS FPZP, YuFPVSH VShchFSH KHCHETEOOSCHNY, YuFP KHRTBCHMEOYE RPRBDEF ZHKHOLGYA कर्नेल_मेन के बारे में। ChEDSH POB NPTsEF VSHCHFSH OE CH OBYUBME ZHBKMB, B UPDETSYNPE स्टार्टअप.o NSCH RPMOPUFSHA LPOFTPMYTHEN Y EUMY KHLBTSE EZP RETCHSHCHN MYOLETKH, FP VKhDEN KHRTBCHMSFSH Y RETCHSHCHNY VBKFBNY DCHPYUOPZ ZHBKMB।

प्रारूप ईएलएफ सार्वजनिक _स्टार्ट एक्सट्रान कर्नेल_मेन सेक्शन ".टेक्स्ट" निष्पादन योग्य _स्टार्ट: movzx edx, dl पुश edx पुश esi पुश ebx lgdt कॉल कर्नेल_मेन @: ;cli ;hlt jmp @b सेक्शन ".data" लिखने योग्य gdt: dq 0 dq 0x00CF9A000000FFFF dq 0x00CF92000000 एफएफएफएफ जीडीटीआर: डीडब्ल्यू $ - जीडीटी डीडी जीडीटी

ओह CHPF Y RPUMEDOYK एलपीडी के बारे में YUYUFPN असेंबलर के बारे में :-)। CHSHCHRPMOSEF RTPUFEKYHA ЪBDББУХ द्वारा - ХМПЦИФШ Ш УФЭЛ ФТИ БТЗХНЭОФБ DMS ZHKHOLGYY कर्नेल_मेन Y RETEDBFSH OEE HRTBCHMEOYE के बारे में। rPUME CHPCHTBFB YЪ OEЈ SDTP KHIPDYF CH VEULPOYUOSCHK GYLM। rP UPZMBYEOYA CHSHCHJPCHB ZHKHOLGYK UI RBTBNEFTSCH UMEDHEF RYIBFSH CH UFEL CH PVTBBPN RPTSDLE। fBLCE LFPF LPD YOYGYBMYBGYY ЪBZTHTSBEF OPCHPE OBYUEOYE CH GDTR - FERTSH FBVMYGB DEULTYRFPTPCH UEZNEOFPCH OBIPDIFUS CH RTPUFTBOUFCHE SDTB Y DBCE EUMY NSCH PFNPO FYTHEN RETCHSCHK NEZBVBKF OE RTPYJPKDEF OILB LYI PYYVPL.

b फर्टश UBNPE Chlhuope - RTPUFEKEEE SDTP सेटिंग ChchupLPZP HTPCHOS के बारे में:

टाइपडेफ़ संरचना (अहस्ताक्षरित लंबा लंबा आधार; अहस्ताक्षरित लंबा लंबा आकार;) BootModuleInfo; शून्य कर्नेल_मेन(चार बूट_डिस्क_आईडी, शून्य *मेमोरी_मैप, बूटमॉड्यूलइन्फो *बूट_मॉड्यूल_लिस्ट) (चार *स्क्रीन_बफर = (शून्य*)0xB8000; चार *संदेश = "हैलो वर्ल्ड!"; अहस्ताक्षरित int i = 24 * 80; जबकि (*msg) (स्क्रीन_बफर) = *संदेश; मैं++;

bFP SDTP OE DEMBEF OYUEZP PUPVEOOOPZP - RTPUFP CHCHCHPDYF UFTPLH "हैलो वर्ल्ड!" RpumedoAA UFTPYULH FELUFPCHPZP LTBOB के बारे में। uFTHHLFKHTB PRYUBOBS CH OBYUBME VkhDEF OHTSOB DMS DPUFKHRB L Uryulkh ЪBZTHTSEOOSCHI NPDHMEK।

chBTsOP RPNOYFSH, YuFP OILBLPK UFBODBTFOPK VYVMYPFELY KH OBU OEF - OBN DPUFHROSCH FPMSHLP FE ZHKHOLGYY, LPFPTSCHE NSCH उडेम्बेन UBNY। च्यू प्रिंटफ, स्ट्रैपी, मेमसीपीवाई वाई एफ. आर. आरटीवाईडीएफस टेबमीपपचचचबीएफएसएच यूबीएनपीयूएफपीएसएफईएमएसएचओपी, ओई आरएससीएचएफबीकेफ्यूश पीवीटीबीएफवाईएफएसएचयूएस लॉयन। ज उमेदहेन चौधरीखुले एनएससीएच ЪБКНЈНУС यूपीडीबॉयन ओबेज़प यूपीवीयूएफसीएचईओओपीजेडपी टीएसकेएचएफएलपी खटीईबीओओपीजेडपी बीओबीएमएमपीजेडबी लिबक, यूएफपीवीएसएच आरटीपीजेडटीबीएनएनएनवाईटीपीसीएचबीएफएसएच वीएसएचएमपी खडीपीवीओईई। FHF OBUYOBEFUS UBNBS YOFETEUOBS YUBUFSH, B RTYOSFSCHE TEYEOYS PE NOPZPN RPCHMYSAF चुआ UFTHLFTH UYUFENSCH के बारे में।

यूवीपीटीएलबी एसडीटीबी

yURPMOSENSCH ZHBKMSCH UPVYTBAFUS CH DCHB LFBRB - LPNRYMSGYS, B आरपीएफपीएन मायोल्पसीएचएलबी। RETCHPN LFBR LPNRYMSFPT RTEPVTBKHEF YUIPDOSCHK LPD CH LPNBODSCH RTPGEUUPTB Y UPITBOSEF CHUY LFP CH PVYAELFOSHCHK ZHBKM के बारे में। LBTSDSCHK NPDHMSH UYUFENSCH UPITBOSEFUS CH PFDEMSHOPN ZHBKME। h LFPN ZHBKME FBL CE UPDETSYFUS YOZHPTNBGYS P ZHKHOLGYSI, PRYUBOOSCHI CH NPDHMY, RPFPNH YЪ PDOPZP ZHBKMB NPTsOP UCHPVPDOP CHSCCHCHBFSH ZHKHOLGYA YЪ DTHZPZP। चेउश एलपीडी सीएच पवेलफोस्ची ज़बकेएमबीआई ओई आरटीईसीएचएसबीओ एल एलपोल्टेफोशचएन बीडीटीईयूबीएन। सीएचएफपीटीपीएन एलएफबीआर मायोलेट यूपीवीटीबीईएफ चुए पवेलफोश जेएचबीकेएमएससीएच सीएच पीडीवाईओ वयोबतोशच के बारे में। आरटीवाई एलएफपीएन एलपीडी आरटीईसीएचएससीएचबीईएफयूएस एल एलपीओएलटीईएफओएचएसएन बीडीटीईयूबीएन (ईयूएमवाई, एलपीओयूओपी, एनएससीएच ओई अपवीटबेन डायोब्न्यूयूली ЪBZTHTSBENKHA VYVMYPFELH), CHNEUFP UUSCHMPL O ZHKHOLGYY RPDUFBCHMSAFUS O HTSOSHE BDTEUB। OBN OHTsOP RPMKHYUFSH CHSHCHIPDE PUPVSHCHK DCHPYUOSCHK ZhBKM के बारे में। ьFP RTPUFP LPD Y DBOOSCH, VEЪ LBLYI-MYVP ЪБЗПМЧЛПЧ (ФП EUФШ ЛФП OE PE І OE ELF)। एच LBUEUFCHE VBPCHPZP BDTEUB YURPMSH'HEFUS BDTEU 0xFFC00000। DMS HRTPEEOYS LFPPZP NSCH PRYYEN CHUЈ, YuFP OBN OHTSOP CH UREGYBMSHOPN ZHTNBFE ULTYRFB ld:

OUTPUT_FORMAT("बाइनरी") ENTRY(_start) अनुभाग ( .text 0xFFC00000: ( *(.text) *(.code) *(.rodata*) ) .data ALIGN(0x1000) : ( *(.data) ) .bss ALIGN(0x1000) : ( *(.bss) ) .empty ALIGN(0x1000) - 1: ( BYTE(0) ) )

ьFPF ULTYRF ZPCHPTYF, YuFP OBY ZHBKM VKhDEF METSBFSH CH RBNSFY OERTETCHCHOSCHN VMPLPN OBUYOBS U BDTEUB 0xFFC00000। एच यूबीएनपीएन ओब्यूबमे वीकेडीईएफ वाईडीएफवाई उएलगिस एलपीडीबी, आरपीएफपीएन यूएलजीआईएस रीड-ओनली डीबूस्ची, एफबीएफएन पीवीएसयूओशी डीबूस्ची, आरपीएफपीएन ओएयोयबीएमवाईवाईटीपीसीएचबूस्ची। TBNET UFTBOYGSCH 4 लेव्स (CHDTHZ NSCH आरपीएफपीएन ЪBIPFYN ЪBEIFYFSH के बारे में HTPCHOE FBVMYGSHCH UFTBOYG LPD ЪBRYUY) के बारे में चुए उलेग्यी CHSHTPCHOOESCH। rPUMEDOEE PRYUBOIE UELGYY.empty OEPVIPDYNP DMS FPZP, YUFPVSH DBTSE OEYOYYYBYMYYPTPCHBOOSCH RETENEOOOSCH ЪBOINBMY NEUFP CH ZHBKME (FBN VHDHF OHMY)। चेद्श ओब्यूबमशोश्चक ЪBZTHYUYL CHSHCHDEMSEF RBNSFSH DMS SDTB THLPCHPDUFCHHSUSH TBNETPN ZHBKMB।

यूपीवीटीबीएफएसएच चुय एसडीटीपी एनपीटीएसओपी उमेधायेनी एलपीएनबीओडीबीएनवाई:

Fasm स्टार्टअप.asm स्टार्टअप.o gcc -c -m32 -फ़्रीस्टैंडिंग -o main.o main.c ld --oformat=binary -melf_i386 -T स्क्रिप्ट.ld -o कर्नेल.बिन स्टार्टअप.o main.o

आरबीटीबीएनईएफटी जीसीसी -फ्रीस्टैंडिंग खएलबीएससीएचबीईएफ एनकेएच पीएफएलएमयूवाईएफएसएच चुए यूएफबीओडीबीटीएफओएसएच वाइवीएमवाईपीएफईएलवाई। चेद्श सिंग रतिचस्बोश एल एलपोल्टेफोपके प्रीटबीजीपूपके उयुफेन, बी एनएससीएच रयेन ओपीछा।

uVPTLB PVTBB DYULB

pVPKDHUSH VE MYYOYI LPNNEOFBTYECH Y RTPUFP RTYCHEDH MYOHLUPCHSHCHK ULTYRF UVPTLY PVTBBB:

Dd if=bin/boot.bios.bin of=bin/boot_sector.bin bs=512 गिनती=1 dd if=bin/boot.bios.bin of=disk/boot.bin bs=1 स्किप=512 cp बिन/कर्नेल .bin डिस्क/kernel.bin bin/make_listfs of=disk.img bs=512 आकार=2880 बूट=bin/boot_sector.bin src=./disk

RTEDRPMBZBEF के अनुसार, YuFP CHUE ULPNRYMYTPCHBOOSCH ZHBKMSCH METSBF Ch बिन Ch फेलखिन LBFBMPZE, B EEЈ YNEEFUS LBFBMPZ डिस्क, Ch LPFPTPN METSYF बूट.cfg UMEDHAEEZP अपडेटबॉयज़:

# कर्नेल Lkernel.bin लोड हो रहा है # 32 बिट कर्नेल S32 बूट करें

eUMY CHU CHUY UDEMBMY RTBCHYMSHOP, RPMKHYUEOOOSCHK PVTB NPTsOP ЪBRKHUFYFSH CH BNHMSFPTE YMY DBTSE TEBMSHOPN TSEMEY CHSHCH RPMKHYUFE RPDPVOKHA LBTFYOKH के बारे में:

उत्पाद विवरण ПДИФ Х ЪБЭИЭЈOOШЧК TETSYN Y RETEDBЈF ENKH KHRTBCHMEOYE। rPMHYUYCH EZP, OBIYE SDTP CHSHCHCHPDYF RPUMEDOAA UFTPLH BLTBO के बारे में। बीएफपी मायश ओबीयूबीएमपी डीपीएमजेडपीजेडपी आरकेएचएफवाई, एनएससीएच रेटीपडिन एल यूबीएनपीके योफेटेयूओपीके युबुफी टीबीटीबीवीपीएफएलवाई। फर्टश चश्चरखुली वीकेएचडीएच जेडपीटीबीजेडीपी वीपीएमईई आरटीपीयूएफएसएचएन डीएमएस चौर्टिसफिस, वीएमबीजेडपीडीबीटीएस युरपीएमएसएच'पचबोया एसजेएसएचएलबी सीएचएसएचचुप्लपजेडपी एचटीपीचोस, एलपीएफपीटीएसएचके एलबीएल एस ओबडेउश चुए वाई एफबीएल ओओबीएएफ। eUMY CHCH OE IPFYFE TBVYTBFSHUS U असेंबलर, NPTSEFE RTPUFP CHOSFSH NPK ZPFPCHSCHK UBZTHYUYL J स्टार्टअप.asm Y YNEOSFSH HCE FPMSHLP UPDETSINPE Main.c, RPULPMSHLH चेउश LPD DP LFPZP OE DYLFHEF TsЈUFLP LBLYE-MYVP RBT BNEFTSH SDTB (LTPNE zhu U LPFPTPK NSCH ЪBZTHTSBENUS) Y RPЪCHPMSEF RPUFTPIFSH UCHPEK VBJE YFP KhZPDOP के बारे में।

bChFPNBFYBGYS UVPTLY YMY मेकफ़ाइल

ChSCH NPZMY ЪBNEFYFSH, YuFP Chthyuokha OBVYCHBFSH UFPMSHLP LPNBOD DPUFBFPYUOP KhFPNYFEMSHOP। एल एफपीएनएच सीई ओई चुएज़्डीबी ईयूएफएसएच ओईपीवीपीडीवाईएनपीयूएफएसएच रिटेलपीएनआरआईएमआईटीसीएचबीएफएसएच चुए ज़हबीकेएमएससीएच। OBRTYNET, EUMY स्टार्टअप.asm OE VSHM YЪNEOЈO, NPTsOP OE CHSHCHCHBFSH fasm। UREGYBMSHOP DMS HRTPEEOYS LPNRYMSGY RTYMPTSEOYK VSHMB RTYDKHNBOB HFYMYFB मेक, LPFPTBS चिपडिफ़ CH UFBODSBTFOHA RPUFBCHLH GCC Y MinGW।

mAVPK मेकफ़ाइल UFPYF YЪ OBVPTB RTBCHYM U FBLPK UFTHHLFKhTPK:

YNSGEMYYMYZHBKMB: yNSRETCHPZPyUIIPDOPZPzhBKMB yNSchFPTPZPyUIIDDOPZPzhBKMB...lPNBODSCHLPNRYMSGYY

RETCHPE RTBCHYMP, LPFPTPE DPMTSOP VShchFSH CH MAVPN मेकफ़ाइल - रत्न सभी। ЪBCHYUYNPUFY GEMY के बारे में UNPFTYF बनाएं सभी Y LPNRYMYTHEF YI, B ЪBFEN CHSHPRMOSEF LPNBODSCH Y LFK GEMY। dMS LBTSDPK DTHZPK GEMY UOBYUBMB UPVYTBAFUS EЈ ЪBCHYUYNPUFY। आरटीवाई एलएफपीएन वाईएनएस जेमी वाई वाईएनएस एबच्युइनपुफेक एनपीजेडएचएफ यूपीसीएचआरबीडीएफएसएच यू येओबनी टेबम्सशोस्ची जेएचबीकेएमपीसीएच। एच एफबीएलपीएन उमख्यूबे रेटेयूवीपीटीएलबी जेमी आरटीपीवाईपीकेडीएफ एफपीएमएसएचएलपी ईयूमी युइपडोयली वीएसएचएमवाई येनोओशच।

eEE PDOB GEMSH, LPFPTBS YBUFP YURPMSHHEFUS CH मेकफ़ाइल - साफ़। eЈ ЪБДББУБ ХДБМІФШ च्यू वयोबतोश ZHBKMSCH, YUFPVSH OBYUBFSH UVPTLH "यू YUYUFPZP MYUFB"। chPF FBL NPTSEF CHSHCHZMSDEFSH मेकफ़ाइल VHI SDTB:

सभी: स्टार्टअप.o main.o स्क्रिप्ट.ld ld --oformat=बाइनरी -melf_i386 -T स्क्रिप्ट.ld -o कर्नेल.बिन स्टार्टअप.o main.o स्टार्टअप.o: स्टार्टअप.i386.asm fasm स्टार्टअप.i386.asm स्टार्टअप.ओ मेन.ओ: मेन.सी जीसीसी -सी -एम32 -फ्रीस्टैंडिंग -ओ मेन.ओ मेन.सी क्लीन: आरएम -वी *.ओ कर्नेल.बिन

bFPF FELUF OEPVIPDYNP UPITBOYFSH CH ZHBKM U Yneoen Makefile (VEY TBUYYTEOYS) CH LBFBMPZ U YUIPDOSHNY FELUFBNY SDTB। FERTSH DPUFBFPYUOP CHSHPRMOYFSH LPNBODH मेक VEЪ RBTBNEFTPC, OBIPDSUSH CH LFPN LBFBMPZE Y NSCH RPMKHYUN ZHBKM कर्नेल.बिन (MYVP UPPVEEOYS PV PYYVLBY, EUMY YUFP-FP RPYMP OE FBL)।

बी सीएचपीएफ एफबीएल एस यूपीवीटीबीए ЪBZTHYUYL:

सभी: बूट.बायोस.बिन बूट.बायोस.बिन: बूट.बायोस.एएसएम फास्म बूट.बायोस.एएसएम बूट.बायोस.बिन साफ: आरएम -वी बूट.बायोस.बिन

वें make_listfs:

सभी: संकलन संकलित करें: make_listfs.c gcc -o make_listfs make_listfs.c साफ़: rm -f make_listfs make_listfs.exe

ओह वाई OBLPOEG TBUULBTSH RTP CHSHCHJPCH DTHZYI मेकफ़ाइल हाँ PDOPZP। DPUFBFPYUOP MEOYCH, YuFPVSH DBTSE ЪBIPDYFSH CH LBFBMPZY U LBTSDSCHN LPNRPEOFPN UYUFENSH, आरपीएफपीएनएच UPЪDBM 1 मेकफ़ाइल, LPFPTSCHK UPVYTBEF UTBH CHUA UYUFENKH के साथ। x NEOS EUFSH RBRLB src, CH OEK RPDLBFBMPZY: बूट, कर्नेल, मेक_लिस्टएफएस। एच यूबीएनपीसी स्रोत ओबीआईपीडीएफयूएस सीएचपीएफ एफबीएलपीसी मेकफ़ाइल:

सभी: मेक -सी बूट/ मेक -सी कर्नेल/ मेक -सी मेक_लिस्टएफएस/ क्लीन: मेक -सी बूट/ क्लीन मेक -सी कर्नेल/ क्लीन मेक -सी मेक_लिस्टएफएस क्लीन

फेरेत्श, ओबीपीडीसश एलबीएफबीएमपीजेई एसआरसी एस आरटीपीयूएफपी रयख मेक वाई आरपीएमह्यूबा आरपीएमओपुफशा यूपीवीटीबूहा उयुफेनख, बी ईयूएमवाई ओब्रीयूबएफएसएच मेक क्लीन, एफपी चुए डीसीएचपीयूओएसएच जेएचबीकेएमएससीएच वीएचडीएचएफ खड्बमोश वाई पुफबोखफस एफपीएमएसएचएलपी वाई व्हिपडॉयल।

ओह वाई सीएच डीपीसीएचईटीईओवाई आरपीयूएमईडीओवाईके अल्टीआरएफ, एलपीएफपीटीएसएचके सीएचएसआरपीएमओएसईएफ आरपीएमओएचए एलपीएनआरआईएमएसजीवाईए वाई यूवीपीटीएलएच चुई एलपीएनआरपीईओएफपीसीएच वाई पीवीटीबीबी डीयूएलबी। h PDOPN LBFBMPZE U OIN OBDP TBBNEUFYFSH src, RHUFPK LBFBMPZ बिन Y LBFBMPZ डिस्क U ZHBKMPN बूट.cfg।

#!/bin/sh मेक -C src cp src/boot/boot.bios.bin बिन/ cp src/kernel/kernel.bin बिन/ cp src/make_listfs/make_listfs बिन/ dd if=bin/boot.bios.bin of=bin/boot_sector.bin bs=512 गिनती=1 dd if=bin/boot.bios.bin of=disk/boot.bin bs=1 स्किप=512 cp बिन/कर्नेल.बिन डिस्क/कर्नेल.बिन बिन/मेक_लिस्टfs of=disk.img bs=512 आकार=2880 Boot=bin/boot_sector.bin src=./disk read -p "जारी रखने के लिए Enter दबाएँ..." डमी

यू FBLYN OBVTPN ULTYRFPCH UVPTLB UYUFENB UFBOPCHYFUS RTEDEMSHOP RTPUFPK, PUPVEOOP EUMY HYUEUFSH, YuFP RPUMEDOYK ULTYRF NPTsOP ЪBRHULBFSH DCHPKOSCHN LMYLPN YJBKMPCHPZP NEOEDCETB। TBMYUOSHE LPNBODSCH CHTPDE dd, cp, rm OE UHEEUFCHHAF RPD विंडोज़, आरपीएफपीएनएच ईЈ RPMSHEPCHBFEMSN RTYZPDYFUS RBBLEF MSYS YMY सिगविन। pDOBLP RTPUFBS UVPTLB CHUEI LPNRPEOFPCH VHDEF TBVPFBFSH DBCE EUMY

rTYNEUBOYE DMS RPMSHEPCHBFEMEK पु विंडोज़

एलडी डीएमएस विंडोज़ ओई अपचुएन आरपीएमओजीओओशचके - पीओ ओई आरपीडीडीटीएसएचबीईएफ सीएचसीएचपीडी यूटीबीएच सीएच वयोबतोशक जेएचबीकेएम, एफपीएमएसएचएलपी सीएच एक्सई। YurtBCHYFSH LFP NPTsOP UPЪDBCH UOBYUBMB EXE (ld OE PVTBFYF Choynboye, YuFP VBPCHSCHE BDTEUB UELGYK OECHPNPTSOSCHE DMS CHEODPCHSHI VYOBTOILPC), BRPPFPN CHSHCHFBEIFSH PFFHDB YUYUFSCHCH RPNPESH objcopy पर अधिक। eUMY CHSH UFPMLOЈFEUSH U FEN, YuFP ld PFLBSCHCHBEFUS UPЪDBCHBFSH ZhBKM कर्नेल.बिन, CHPURPMSHKFEUSH CHPF FBLYN मेकफ़ाइल VHI SDTB:

सभी: स्टार्टअप.ओ मेन.ओ स्क्रिप्ट.एलडी एलडी -मेल्फ़_आई386 -टी स्क्रिप्ट.एलडी -ओ कर्नेल.बिन स्टार्टअप.ओ मेन.ओ ओबीजेकॉपी कर्नेल.बिन -ओ बाइनरी स्टार्टअप.ओ: स्टार्टअप.आई386.एएसएम एफएएसएम स्टार्टअप.आई386 .asm स्टार्टअप.ओ मेन.ओ: मेन.सी जीसीसी -सी -एम32 -फ्रीस्टैंडिंग -ओ मेन.ओ मेन.सी क्लीन: आरएम -वी *.ओ कर्नेल.बिन

ъБПДОП ХВЭТИФЭ УФТПЛХ OUTPUT_FORMAT("बाइनरी") और स्क्रिप्ट.एलडी। फेरेत्श वाई आरपीडी विंडोज आरपीएमख्युफस यूपीवीटीबीएफएसएच एसडीटीपी उयुफेंश।

ъБЗТХЪЛБ УИУФЭНШЧ TEBMSHOPK NBYYOE के बारे में

rPUME FBLYI KHUREIPCH एलएफपी ओई आरटीईडीयूएफबीसीएचएमएसईएफ आरटीपीवीमेन। यू आरपीएनपीईएसएचए एचएक्सडी सीएच विंडोज पीएफएलटीपीकेएफई ड्यूलेफख वाईएमवाई झमेलीएच, सीएचएसएचवीटीबीसीएच सीएचबीटीवाईबीओएफ "पीएफएलटीएसएचएफएसएच ड्यूल"। आरटीवाई पीएफएलटीएसएचएफवाई झमेली सीएचबीटीएसपी पीएफएलटीएससीएचएफएसएच येनूओप उबीएनएच झमेलीख, बोए एट टीबी'डेम। h DTHZPK CHLMBDLE PFLTPKFE डिस्क.img, CHSHCHDEMYFE EZP UPDETSINPE RPMOPUFSHA Y ULPRYTHKFE OB DYUL U EZP UBNPZP OBYUBMB। rPUME LFPPZP NPTsOP OBTSBFSH "uPITBOIFSH" Y DPTsDBFSHUS PLPOYUBOYS ЪBRYUY। चुए डबूश जेएमवाई ड्यूलेफ आरटीवाई एलएफपीएन वीएचडीएचएफ होयुफत्सेओशच, बी डीएमएस एफपीजेडपी, यूएफपीवीएसएच ईईयूआरपीएमएसएचपीसीएचबीएफएसएच यूओपीसीएचबी आरपी ओब्यूओया, ईईआर आरटीवाईडीएफस Ъबीओपीसीएचपी पीएफजेडएचपीटीएनबीएफवाईटीपीसीएचबीएफएसएच के बारे में!

rPMSHPCHBFEMY Linux NPZHF RPUFKHRYFSH RTPEE - CHSHRPMOYFSH UREGYBMSHOHA LPNBODH CH FETNYOBME। डीएमएस ड्यूलेफ़श:

Dd if=disk.img of=/dev/fd0

डीएमएस झमेली:

Dd if=disk.img of=/dev/sdX

chNEUFP sdX OBDP RPDUFBCHYFSH OBUFPSEEE YNS KHUFTPKUFCHB (sda, sdb, sdc, sdd Y F. D.)। ZMBCHOPE RTY LFPN OE RETERKHFBFSH Y OE ЪBRYUBFSH PVTB UYUFENOSHCHK DYUL, HOYUFPTSYCH CHUE DBOOSCH के बारे में। TBHNEEFUS, PVE LPNBODSCH DPMTSOSCHCHSHCHRPMOSFSHUS PF YNEOY रूट YMY Y RPNPESH सुडो।

rPUME LFPPZP OBDP OBUFTPIFSH CH BIOS ЪБЗТХЛХ У ДУЛЭФШЧ ІМИ ЖМИЛХ (UFBTSCHE BIOS OE RPDDETSYCHBAF ZHMEYLY) Y OBUMBTSDBFSHUS CHYDPN "हैलो वर्ल्ड"।

ъBLMAYUEOOYE

ओह CHPF UPVUFCHOOOP Y CHUЈ UEZPDOS के बारे में। nsch OBLPOEG-FP ЪBLPOYUMY RTPZTBNNNYTPCHBOIE OB असेंबलर (IPFS Ch u CHU TBCHOP RTYDFUS YOPZDB DEMBFSH BUUENVMETOSCHE CHUFBCHLY DMS TBVPFSH U PVPTKHDPCHBOYEN) Y RETEYMY SB L CHCHUPLPZP HTPCHOS। eEE प्युओश NOPZP RTEDUFPYF UDEMBFSH। NSC NPTSEFE HCE RTPCHPDYFSH TBMYUOSCH LURETYNEOFSH, JNEOSS NPK main.c, FPMSHLP KHYUFYFE, YuFP MAVBS PYYVLB (DPUFHR L OEURTPEGYTPCHBOOPC RBNSFY, RITCHED के बारे में डेमोय) FL रेटेबीज़थाइल YMY ЪBCHYUBOYA UYUFENSCH ( NSCH RPLB OE PVTBVBFSCHBEN YULMAYUEOYS, आरपीएफपीएनएच RTPGEUUPT OE NPTSEF RTDPDPMTSYFSH TBVPFKH RPUME PYYVLY ) . डीपी चुफ़्टेयु!

MAvsche CHPRPTUSCH CHSC NPTSEFE ЪBDBFSH NPK BDTEU के बारे में: [ईमेल सुरक्षित]. वाई डीबी, उइक्यूबु यूबीएनपीई चटेन्स डीएमएस टीबीम्युओशी येडेक आरपी एलपीओगेर्गी पु वाई आरटीईडीएमपीटीएसओवाईके।

ऑपरेटिंग सिस्टम लिखने के लिए आपको क्या जानना आवश्यक है

ऑपरेटिंग सिस्टम बनाना प्रोग्रामिंग में सबसे कठिन कार्यों में से एक है क्योंकि इसके लिए कंप्यूटर कैसे काम करता है इसके बारे में व्यापक और जटिल ज्ञान की आवश्यकता होती है। जो लोग? आइए नीचे जानें।

ओएस क्या है?

एक ऑपरेटिंग सिस्टम (ओएस) एक सॉफ्टवेयर है जो कंप्यूटर हार्डवेयर और उसके संसाधनों के साथ काम करता है और कंप्यूटर के हार्डवेयर और सॉफ्टवेयर के बीच एक सेतु है।

पहली पीढ़ी के कंप्यूटरों में ऑपरेटिंग सिस्टम नहीं थे। पहले कंप्यूटर के प्रोग्राम में सिस्टम के सीधे संचालन, परिधीय उपकरणों के साथ संचार और गणना के लिए कोड शामिल थे, जिसके लिए यह प्रोग्राम लिखा गया था। इस स्थिति के कारण, यहां तक ​​कि तर्क में सरल प्रोग्रामों को भी सॉफ़्टवेयर में लागू करना कठिन था।

जैसे-जैसे कंप्यूटर अधिक विविध और जटिल होते गए, ऐसे प्रोग्राम लिखना जो ओएस और एप्लिकेशन दोनों के रूप में काम करते थे, बस असुविधाजनक हो गए। इसलिए, प्रोग्राम को लिखना आसान बनाने के लिए, कंप्यूटर मालिकों ने सॉफ़्टवेयर विकसित करना शुरू किया। इस प्रकार ऑपरेटिंग सिस्टम प्रकट हुए।

ओएस उपयोगकर्ता प्रोग्राम को चलाने के लिए आवश्यक सभी चीजें प्रदान करता है। उनकी उपस्थिति का मतलब था कि प्रोग्रामों को अब कंप्यूटर पर काम की पूरी मात्रा को नियंत्रित करने की आवश्यकता नहीं है (यह इनकैप्सुलेशन का एक उत्कृष्ट उदाहरण है)। अब प्रोग्रामों को विशेष रूप से ऑपरेटिंग सिस्टम के साथ काम करने की आवश्यकता होती है, और सिस्टम स्वयं संसाधनों और बाह्य उपकरणों (कीबोर्ड, प्रिंटर) के साथ काम करने की देखभाल करता है।

ऑपरेटिंग सिस्टम का संक्षिप्त इतिहास

सी भाषा

जैसा कि ऊपर बताया गया है, OS लिखने के लिए कई उच्च स्तरीय प्रोग्रामिंग भाषाएँ हैं। हालाँकि, उनमें से सबसे लोकप्रिय सी है।

आप इस भाषा को यहां से सीखना शुरू कर सकते हैं। यह संसाधन आपको बुनियादी अवधारणाओं से परिचित कराएगा और आपको अधिक उन्नत कार्यों के लिए तैयार करेगा।

"लर्न सी द हार्ड वे" एक अन्य पुस्तक का शीर्षक है। सामान्य सिद्धांत के अलावा, इसमें कई व्यावहारिक समाधान भी शामिल हैं। यह ट्यूटोरियल भाषा के सभी पहलुओं को कवर करेगा।

या आप इनमें से कोई एक किताब चुन सकते हैं:

  • कर्निघन और रिची द्वारा "द सी प्रोग्रामिंग लैंग्वेज";
  • पैरी और मिलर द्वारा "सी प्रोग्रामिंग एब्सोल्यूट बिगिनर्स गाइड"।

ओएस विकास

कंप्यूटर विज्ञान, असेंबली भाषा और सी के संबंध में आपको जो कुछ भी जानना आवश्यक है उसमें महारत हासिल करने के बाद, आपको वास्तविक ओएस विकास के बारे में कम से कम एक या दो किताबें पढ़नी चाहिए। इसके लिए यहां कुछ संसाधन दिए गए हैं:

"स्क्रैच से लिनक्स"। लिनक्स ऑपरेटिंग सिस्टम को असेंबल करने की प्रक्रिया पर यहां चर्चा की गई है (पाठ्यपुस्तक का रूसी सहित कई भाषाओं में अनुवाद किया गया है)। यहां, अन्य पाठ्यपुस्तकों की तरह, आपको सभी आवश्यक बुनियादी ज्ञान प्रदान किया जाएगा। उन पर भरोसा करते हुए, आप OS बनाने में अपना हाथ आज़मा सकते हैं। OS के सॉफ़्टवेयर भाग को और अधिक पेशेवर बनाने के लिए, पाठ्यपुस्तक में कुछ अतिरिक्त चीज़ें शामिल हैं: "

कर्नेल विकसित करना उचित रूप से आसान काम नहीं माना जाता है, लेकिन कोई भी एक साधारण कर्नेल लिख सकता है। कर्नेल हैकिंग के जादू का अनुभव करने के लिए, आपको बस कुछ परंपराओं का पालन करना होगा और असेंबलर भाषा में महारत हासिल करनी होगी। इस लेख में हम आपको दिखाएंगे कि यह कैसे करना है।


हैलो वर्ल्ड!

आइए एक कर्नेल लिखें जो x86-संगत सिस्टम पर GRUB के माध्यम से बूट होगा। हमारा पहला कर्नेल स्क्रीन पर एक संदेश दिखाएगा और वहीं रुक जाएगा।

x86 मशीनें कैसे बूट होती हैं

कर्नेल को लिखने के तरीके के बारे में सोचने से पहले, आइए देखें कि कंप्यूटर कैसे बूट होता है और कर्नेल पर नियंत्रण स्थानांतरित करता है। अधिकांश x86 प्रोसेसर रजिस्टरों में बूट के बाद विशिष्ट मान होते हैं। इंस्ट्रक्शन पॉइंटर रजिस्टर (ईआईपी) में उस इंस्ट्रक्शन का पता होता है जिसे प्रोसेसर द्वारा निष्पादित किया जाएगा। इसका हार्डकोडेड मान 0xFFFFFF0 है। यानी, x86 प्रोसेसर हमेशा भौतिक पते 0xFFFFFF0 से निष्पादन शुरू करेगा। यह 32-बिट एड्रेस स्पेस के अंतिम 16 बाइट्स हैं। इस पते को रीसेट वेक्टर कहा जाता है।

चिपसेट में मौजूद मेमोरी कार्ड बताता है कि पता 0xFFFFFFF0 BIOS के एक विशिष्ट भाग को संदर्भित करता है, न कि रैम को। हालाँकि, तेजी से पहुंच के लिए BIOS खुद को रैम में कॉपी कर लेता है - इस प्रक्रिया को "शैडोइंग" कहा जाता है, जिससे एक शैडो कॉपी बनती है। तो पता 0xFFFFFFFF0 में केवल मेमोरी में उस स्थान पर जाने के लिए एक निर्देश होगा जहां BIOS ने खुद को कॉपी किया है।

तो, BIOS निष्पादित होना शुरू हो जाता है। सबसे पहले, यह उन डिवाइसों की तलाश करता है जिनसे यह सेटिंग्स में निर्दिष्ट क्रम में बूट हो सकता है। यह एक "मैजिक नंबर" के लिए मीडिया की जांच करता है जो बूट करने योग्य डिस्क को नियमित डिस्क से अलग करता है: यदि पहले सेक्टर में बाइट्स 511 और 512 0xAA55 हैं, तो डिस्क बूट करने योग्य है।

एक बार जब BIOS को बूट डिवाइस मिल जाता है, तो यह पहले सेक्टर की सामग्री को 0x7C00 पते से शुरू करके रैम में कॉपी कर देगा, और फिर निष्पादन को उस पते पर ले जाएगा और अभी लोड किए गए कोड को निष्पादित करना शुरू कर देगा। इस कोड को बूटलोडर कहा जाता है।

बूटलोडर कर्नेल को भौतिक पते 0x100000 पर लोड करता है। अधिकांश लोकप्रिय x86 कर्नेल इसका उपयोग करते हैं।

सभी x86-संगत प्रोसेसर एक आदिम 16-बिट मोड में प्रारंभ होते हैं जिसे "वास्तविक मोड" कहा जाता है। GRUB बूटलोडर CR0 रजिस्टर के निचले बिट को एक पर सेट करके प्रोसेसर को 32-बिट संरक्षित मोड में स्विच करता है। इसलिए, कर्नेल 32-बिट संरक्षित मोड में लोड होना शुरू हो जाता है।

ध्यान दें कि GRUB, लिनक्स कर्नेल के मामले में, उपयुक्त बूट प्रोटोकॉल का चयन करता है और कर्नेल को वास्तविक मोड में बूट करता है। लिनक्स कर्नेल स्वचालित रूप से संरक्षित मोड में स्विच हो जाता है।

हमें क्या जरूरत है

  • x86 संगत कंप्यूटर (स्पष्ट रूप से)
  • लिनक्स
  • NASM असेंबलर,
  • एलडी (जीएनयू लिंकर),
  • ग्रब.

असेंबली भाषा प्रवेश बिंदु

बेशक, हम सब कुछ सी में लिखना चाहेंगे, लेकिन हम असेंबलर का उपयोग करने से पूरी तरह से बच नहीं पाएंगे। हम x86 असेंबलर में एक छोटी फ़ाइल लिखेंगे जो हमारे कर्नेल के लिए शुरुआती बिंदु बन जाएगी। असेंबली कोड केवल एक बाहरी फ़ंक्शन को कॉल करेगा जिसे हम C में लिखेंगे, और फिर प्रोग्राम को निष्पादित होने से रोक देंगे।

हम असेंबली कोड को अपने कर्नेल के लिए शुरुआती बिंदु कैसे बना सकते हैं? हम एक लिंकर स्क्रिप्ट का उपयोग करते हैं जो ऑब्जेक्ट फ़ाइलों को लिंक करती है और अंतिम कर्नेल निष्पादन योग्य फ़ाइल बनाती है (मैं नीचे और अधिक समझाऊंगा)। इस स्क्रिप्ट में, हम सीधे संकेत देंगे कि हम चाहते हैं कि हमारी बाइनरी 0x100000 पते पर डाउनलोड हो। यह वह पता है, जैसा कि मैंने पहले ही लिखा है, जिस पर बूटलोडर कर्नेल में प्रवेश बिंदु देखने की उम्मीद करता है।

यहाँ असेंबलर कोड है.

कर्नेल.asm
बिट्स 32 सेक्शन .टेक्स्ट ग्लोबल स्टार्ट एक्सटर्न केमेन स्टार्ट: सीएलआई मूव ईएसपी, स्टैक_स्पेस कॉल केमेन एचएलटी सेक्शन .बीएसएस आरएसबी 8192 स्टैक_स्पेस:

पहला बिट्स 32 निर्देश x86 असेंबलर नहीं है, बल्कि एक NASM निर्देश है जो प्रोसेसर को 32-बिट मोड में चलाने के लिए कोड उत्पन्न करने के लिए कहता है। यह हमारे उदाहरण के लिए आवश्यक नहीं है, लेकिन इसे स्पष्ट रूप से इंगित करना अच्छा अभ्यास है।

दूसरी पंक्ति पाठ अनुभाग से शुरू होती है, जिसे कोड अनुभाग भी कहा जाता है। हमारा सारा कोड यहां जाएगा.

ग्लोबल एक और NASM निर्देश है, यह हमारे कोड में प्रतीकों को वैश्विक घोषित करता है। यह लिंकर को प्रारंभ चिह्न ढूंढने की अनुमति देगा, जो हमारे प्रवेश बिंदु के रूप में कार्य करता है।

kmain एक फ़ंक्शन है जिसे हमारी कर्नेल.सी फ़ाइल में परिभाषित किया जाएगा। बाहरी घोषणा करता है कि फ़ंक्शन कहीं और घोषित किया गया है।

इसके बाद स्टार्ट फ़ंक्शन आता है, जो kmain को कॉल करता है और प्रोसेसर को hlt निर्देश के साथ बंद कर देता है। इंटरप्ट एचएलटी के बाद प्रोसेसर को जगा सकता है, इसलिए हम पहले सीएलआई (स्पष्ट इंटरप्ट) निर्देश के साथ इंटरप्ट को अक्षम करते हैं।

आदर्श रूप से, हमें स्टैक के लिए कुछ मात्रा में मेमोरी आवंटित करनी चाहिए और स्टैक पॉइंटर (एएसपी) को उस पर इंगित करना चाहिए। ऐसा लगता है कि GRUB वैसे भी हमारे लिए ऐसा करता है, और इस बिंदु पर स्टैक पॉइंटर पहले से ही सेट है। हालाँकि, बस मामले में, आइए बीएसएस अनुभाग में कुछ मेमोरी आवंटित करें और स्टैक पॉइंटर को इसकी शुरुआत में इंगित करें। हम resb निर्देश का उपयोग करते हैं - यह बाइट्स में निर्दिष्ट मेमोरी को सुरक्षित रखता है। फिर स्मृति के आरक्षित टुकड़े के किनारे को इंगित करने वाला एक निशान छोड़ा जाता है। Kmain को कॉल करने से ठीक पहले, स्टैक पॉइंटर (esp) को mov निर्देश द्वारा इस क्षेत्र में निर्देशित किया जाता है।

सी में कर्नेल

कर्नेल.asm फ़ाइल में हमने kmain() फ़ंक्शन को कॉल किया। तो C कोड में, निष्पादन वहीं से शुरू होगा।

कर्नेल.सी
शून्य किमी (शून्य) ( स्थिरांक char *str = "मेरा पहला कर्नेल"; char *vidptr = (char*)0xb8000; अहस्ताक्षरित int i = 0; अहस्ताक्षरित int j = 0; while(j< 80 * 25 * 2) { vidptr[j] = " "; vidptr = 0x07; j = j + 2; } j = 0; while(str[j] != "\0") { vidptr[i] = str[j]; vidptr = 0x07; ++j; i = i + 2; } return; }

हमारा कर्नेल केवल स्क्रीन को साफ़ करेगा और मेरी पहली कर्नेल लाइन को प्रिंट करेगा।

सबसे पहले, हम एक vidptr पॉइंटर बनाते हैं जो 0xb8000 को इंगित करता है। संरक्षित मोड में, यह वीडियो मेमोरी की शुरुआत है। टेक्स्ट स्क्रीन मेमोरी केवल एड्रेस स्पेस का हिस्सा है। स्क्रीन I/O के लिए मेमोरी का एक भाग आवंटित किया जाता है, जो 0xb8000 पते से शुरू होता है; इसमें 80 ASCII वर्णों की 25 पंक्तियाँ रखी जाती हैं।

टेक्स्ट मेमोरी में प्रत्येक वर्ण को 16 बिट्स (2 बाइट्स) द्वारा दर्शाया जाता है, न कि 8 बिट्स (1 बाइट) द्वारा जिसका हम उपयोग करते हैं। पहला बाइट कैरेक्टर का ASCII कोड है, और दूसरा बाइट विशेषता-बाइट है। यह वर्ण प्रारूप की परिभाषा है, जिसमें उसका रंग भी शामिल है।

वर्ण s हरे को काले पर आउटपुट करने के लिए, हमें वीडियो मेमोरी के पहले बाइट में s और दूसरे बाइट में मान 0x02 डालना होगा। यहां 0 का मतलब काला बैकग्राउंड और 2 का मतलब हरा रंग है। हम हल्के भूरे रंग का उपयोग करेंगे, इसका कोड 0x07 है।

पहले while लूप में, प्रोग्राम 80 वर्णों की सभी 25 पंक्तियों को 0x07 विशेषता के साथ खाली वर्णों से भरता है। इससे स्क्रीन साफ़ हो जाएगी.

दूसरे लूप में, नल-टर्मिनेटेड स्ट्रिंग मेरा पहला कर्नेल वीडियो मेमोरी में लिखा जाता है और प्रत्येक वर्ण को 0x07 की एक विशेषता-बाइट प्राप्त होती है। इसे एक स्ट्रिंग आउटपुट करना चाहिए.

लेआउट

अब हमें NASM का उपयोग करके कर्नेल.एएसएम को एक ऑब्जेक्ट फ़ाइल में संकलित करना होगा, और फिर कर्नेल.सी को किसी अन्य ऑब्जेक्ट फ़ाइल में संकलित करने के लिए जीसीसी का उपयोग करना होगा। हमारा कार्य इन ऑब्जेक्ट्स को लोडिंग के लिए उपयुक्त निष्पादन योग्य कर्नेल में लिंक करना है। ऐसा करने के लिए, हमें लिंकर (एलडी) के लिए एक स्क्रिप्ट लिखनी होगी, जिसे हम एक तर्क के रूप में पारित करेंगे।

लिंक.एलडी
OUTPUT_FORMAT(elf32-i386) ENTRY(start) अनुभाग ( . = 0x100000; .text: ( *(.text) ) .data: ( *(.data) ) .bss: ( *(.bss) ) )

यहां हमने सबसे पहले अपनी निष्पादन योग्य फ़ाइल के प्रारूप (OUTPUT_FORMAT) को 32-बिट ईएलएफ (निष्पादन योग्य और लिंक करने योग्य प्रारूप) पर सेट किया है, जो x86 आर्किटेक्चर के लिए यूनिक्स-आधारित सिस्टम के लिए एक मानक बाइनरी प्रारूप है।

ENTRY एक तर्क लेता है। यह उस प्रतीक का नाम निर्दिष्ट करता है जो निष्पादन योग्य फ़ाइल के प्रवेश बिंदु के रूप में काम करेगा।

अनुभाग हमारे लिए सबसे महत्वपूर्ण हिस्सा है. यहां हम अपनी निष्पादन योग्य फ़ाइल के लेआउट को परिभाषित करते हैं। हम परिभाषित कर सकते हैं कि विभिन्न अनुभागों को कैसे संयोजित किया जाएगा और प्रत्येक अनुभाग को कहाँ रखा जाएगा।

घुंघराले ब्रेसिज़ में जो सेक्शन अभिव्यक्ति का पालन करते हैं, बिंदु स्थान काउंटर को इंगित करता है। इसे SECTIONS ब्लॉक की शुरुआत में स्वचालित रूप से 0x0 पर प्रारंभ किया जाता है, लेकिन एक नया मान निर्दिष्ट करके इसे बदला जा सकता है।

मैंने पहले लिखा था कि कर्नेल कोड 0x100000 पते से शुरू होना चाहिए। यही कारण है कि हम स्थिति काउंटर को 0x100000 मान निर्दिष्ट करते हैं।

लाइन.टेक्स्ट: ( *(.टेक्स्ट) ) पर एक नजर डालें। यहां तारांकन एक मास्क निर्दिष्ट करता है जो किसी भी फ़ाइल नाम से मेल खा सकता है। तदनुसार, अभिव्यक्ति *(.text) का अर्थ सभी इनपुट फ़ाइलों में सभी इनपुट .text अनुभाग है।

परिणामस्वरूप, लिंकर सभी ऑब्जेक्ट फ़ाइलों के सभी टेक्स्ट अनुभागों को निष्पादन योग्य फ़ाइल के टेक्स्ट अनुभाग में मर्ज कर देगा और इसे स्थिति काउंटर में निर्दिष्ट पते पर रख देगा। हमारे निष्पादन योग्य का कोड अनुभाग 0x100000 पते पर प्रारंभ होगा।

लिंकर द्वारा टेक्स्ट अनुभाग तैयार करने के बाद, स्थिति काउंटर मान 0x100000 प्लस टेक्स्ट अनुभाग का आकार होगा। इसी तरह, डेटा और बीएसएस अनुभागों को मर्ज किया जाएगा और स्थिति काउंटर द्वारा निर्दिष्ट पते पर रखा जाएगा।

GRUB और मल्टीबूट

अब हमारी सभी फ़ाइलें कर्नेल बनाने के लिए तैयार हैं। लेकिन चूंकि हम GRUB का उपयोग करके कर्नेल को बूट करेंगे, इसलिए एक और चरण बाकी है।

बूटलोडर का उपयोग करके विभिन्न x86 कर्नेल लोड करने के लिए एक मानक है। इसे "मल्टीबूट स्पेसिफिकेशन" कहा जाता है। GRUB केवल वही कर्नेल लोड करेगा जो उससे मेल खाते हों।

इस विनिर्देश के अनुसार, कर्नेल में पहले 8 किलोबाइट में एक हेडर (मल्टीबूट हेडर) हो सकता है। इस हेडर में तीन फ़ील्ड होनी चाहिए:

  • जादू- इसमें "जादुई" संख्या 0x1BADB002 शामिल है, जिसके द्वारा हेडर की पहचान की जाती है;
  • झंडे- यह फ़ील्ड हमारे लिए महत्वपूर्ण नहीं है, आप इसे शून्य छोड़ सकते हैं;
  • अंततः,- चेकसम, जादू और झंडे फ़ील्ड में जोड़े जाने पर शून्य देना चाहिए।

हमारी कर्नेल.एएसएम फ़ाइल अब इस तरह दिखेगी।

कर्नेल.asm
बिट्स 32 सेक्शन .टेक्स्ट; मल्टीबूट स्पेक अलाइन 4 डीडी 0x1बीएडीबी002;

डीडी निर्देश 4-बाइट डबल शब्द निर्दिष्ट करता है।

कर्नेल को असेंबल करना

तो, कर्नेल.एएसएम और कर्नेल.सी से एक ऑब्जेक्ट फ़ाइल बनाने और हमारी स्क्रिप्ट का उपयोग करके उन्हें लिंक करने के लिए सब कुछ तैयार है। हम कंसोल में लिखते हैं:

$ nasm -f elf32 कर्नेल.asm -o kasm.o

इस कमांड का उपयोग करके, असेंबलर ELF-32 बिट प्रारूप में एक फ़ाइल kasm.o बनाएगा। अब जीसीसी की बारी है:

$ जीसीसी -एम32 -सी कर्नेल.सी -ओ केसी.ओ

-सी पैरामीटर इंगित करता है कि संकलन के बाद फ़ाइल को लिंक करने की आवश्यकता नहीं है। हम इसे स्वयं करेंगे:

$ ld -m elf_i386 -T link.ld -o कर्नेल kasm.o kc.o

यह कमांड हमारी स्क्रिप्ट के साथ लिंकर चलाएगा और कर्नेल नामक एक निष्पादन योग्य फ़ाइल उत्पन्न करेगा।

चेतावनी

कर्नेल हैकिंग आभासी वातावरण में सबसे अच्छी तरह से की जाती है। GRUB के बजाय QEMU में कर्नेल चलाने के लिए, qemu-system-i386 -kernelkernel कमांड का उपयोग करें।

GRUB की स्थापना करना और कर्नेल प्रारंभ करना

GRUB के लिए आवश्यक है कि कर्नेल फ़ाइल का नाम कर्नेल का अनुसरण करे-<версия>. तो चलिए फ़ाइल का नाम बदलें - मैं अपना कर्नेल-701 कहूंगा।

अब हम कर्नेल को /boot निर्देशिका में डालते हैं। इसके लिए सुपरयूज़र विशेषाधिकारों की आवश्यकता होगी.

आपको GRUB कॉन्फ़िगरेशन फ़ाइल grub.cfg में कुछ इस तरह जोड़ना होगा:

शीर्षक myKernel रूट (hd0,0) कर्नेल /बूट/कर्नेल-701 ro

यदि हिडनमेनू निर्देश शामिल है तो उसे हटाना न भूलें।

ग्रब 2

GRUB 2 में हमारे द्वारा बनाए गए कर्नेल को चलाने के लिए, जो नए वितरणों में डिफ़ॉल्ट रूप से आपूर्ति की जाती है, आपकी कॉन्फ़िगरेशन इस तरह दिखनी चाहिए:

मेनूएंट्री "कर्नेल 701" (सेट रूट = "hd0,msdos1" मल्टीबूट /बूट/कर्नेल-701 ro)

इस अतिरिक्त योगदान के लिए रूबेन लगुआना को धन्यवाद।

अपने कंप्यूटर को रीबूट करें और आपको सूची में अपना कर्नेल देखना चाहिए! और जब आप इसे सेलेक्ट करेंगे तो आपको वही लाइन दिखाई देगी।



यह आपका मूल है!

कीबोर्ड और स्क्रीन समर्थन के साथ कर्नेल लिखना

हमने एक न्यूनतम कर्नेल पर काम पूरा कर लिया है जो GRUB के माध्यम से बूट होता है, संरक्षित मोड में चलता है, और स्क्रीन पर एक लाइन प्रिंट करता है। इसे विस्तारित करने और एक कीबोर्ड ड्राइवर जोड़ने का समय आ गया है जो कीबोर्ड से अक्षरों को पढ़ेगा और उन्हें स्क्रीन पर प्रदर्शित करेगा।

हम I/O पोर्ट के माध्यम से I/O उपकरणों के साथ संचार करेंगे। मूलतः, वे I/O बस के पते मात्र हैं। पढ़ने और लिखने के संचालन के लिए विशेष प्रोसेसर निर्देश हैं।

बंदरगाहों के साथ कार्य करना: पढ़ना और आउटपुट

रीड_पोर्ट: mov edx, in al, dx ret राइट_पोर्ट: mov edx, mov al, out dx, al ret

x86 सेट में शामिल इन और आउट निर्देशों का उपयोग करके I/O पोर्ट तक पहुंच प्राप्त की जाती है।

read_port में, पोर्ट नंबर को एक तर्क के रूप में पारित किया जाता है। जब कंपाइलर किसी फ़ंक्शन को कॉल करता है, तो यह सभी तर्कों को स्टैक पर धकेल देता है। स्टैक पॉइंटर का उपयोग करके तर्क को edx रजिस्टर में कॉपी किया जाता है। डीएक्स रजिस्टर ईडीएक्स रजिस्टर का निचला 16 बिट है। यहां दिया गया निर्देश dx में दिए गए पोर्ट नंबर को पढ़ता है और परिणाम को al में डालता है। अल रजिस्टर ईएक्स रजिस्टर का निचला 8 बिट है। आपको कॉलेज से याद होगा कि फ़ंक्शंस द्वारा लौटाए गए मान ईएक्स रजिस्टर के माध्यम से पारित किए जाते हैं। तो read_port हमें I/O पोर्ट से पढ़ने की अनुमति देता है।

राइट_पोर्ट फ़ंक्शन इसी तरह से काम करता है। हम दो तर्क लेते हैं: पोर्ट नंबर और वह डेटा जो लिखा जाएगा। आउट इंस्ट्रक्शन एक पोर्ट पर डेटा लिखता है।

बीच में आता है

अब, ड्राइवर लिखने से पहले, हमें यह समझने की ज़रूरत है कि प्रोसेसर को कैसे पता चलता है कि किसी एक डिवाइस ने कोई ऑपरेशन किया है।

मतदान उपकरणों का सबसे सरल समाधान है - एक सर्कल में उनकी स्थिति की लगातार जांच करना। यह, स्पष्ट कारणों से, अप्रभावी और अव्यवहारिक है। तो यहीं पर रुकावटें आती हैं। इंटरप्ट किसी डिवाइस या प्रोग्राम द्वारा प्रोसेसर को भेजा गया एक सिग्नल है जो इंगित करता है कि कोई घटना घटी है। इंटरप्ट का उपयोग करके, हम उपकरणों को सर्वेक्षण करने की आवश्यकता से बच सकते हैं और केवल उन घटनाओं पर प्रतिक्रिया देंगे जिनमें हमारी रुचि है।

प्रोग्रामेबल इंटरप्ट कंट्रोलर (PIC) नामक एक चिप x86 आर्किटेक्चर में व्यवधान के लिए जिम्मेदार है। यह हार्डवेयर इंटरप्ट और रूट को संभालता है और उन्हें उपयुक्त सिस्टम इंटरप्ट में बदल देता है।

जब उपयोगकर्ता डिवाइस के साथ कुछ करता है, तो इंटरप्ट रिक्वेस्ट (आईआरक्यू) नामक एक पल्स पीआईसी चिप को भेजा जाता है। PIC प्राप्त व्यवधान को सिस्टम व्यवधान में बदल देता है और प्रोसेसर को एक संदेश भेजता है कि वह जो कर रहा है उसे रोकने का समय आ गया है। आगे की रुकावट को संभालना कर्नेल का कार्य है।

पीआईसी के बिना, हमें यह देखने के लिए सिस्टम में मौजूद सभी उपकरणों का सर्वेक्षण करना होगा कि क्या उनमें से किसी के साथ कोई घटना घटी है।

आइए देखें कि यह कीबोर्ड के साथ कैसे काम करता है। कीबोर्ड पोर्ट 0x60 और 0x64 पर लटका रहता है। पोर्ट 0x60 डेटा भेजता है (जब कोई बटन दबाया जाता है), और पोर्ट 0x64 स्थिति भेजता है। हालाँकि, हमें यह जानना होगा कि इन पोर्ट को वास्तव में कब पढ़ना है।

रुकावटें यहां काम आती हैं. जब बटन दबाया जाता है, तो कीबोर्ड IRQ1 इंटरप्ट लाइन के माध्यम से एक PIC सिग्नल भेजता है। PIC अपने आरंभीकरण के दौरान सहेजे गए ऑफ़सेट मान को संग्रहीत करता है। यह इंटरप्ट वेक्टर बनाने के लिए इस पैडिंग में इनपुट लाइन नंबर जोड़ता है। प्रोसेसर तब इंटरप्ट हैंडलर को उसके नंबर के अनुरूप पता देने के लिए इंटरप्ट डिस्क्रिप्टर टेबल (आईडीटी) नामक एक डेटा संरचना को देखता है।

फिर उस पते पर कोड निष्पादित किया जाता है और व्यवधान को संभालता है।

आईडीटी सेट करें

स्ट्रक्चर आईडीटी_एंट्री (अहस्ताक्षरित लघु पूर्णांक ऑफसेट_लोअरबिट्स; अहस्ताक्षरित लघु पूर्णांक चयनकर्ता; अहस्ताक्षरित चार शून्य; अहस्ताक्षरित चार प्रकार_एटीआर; अहस्ताक्षरित लघु पूर्णांक ऑफसेट_हायरबिट्स; ); संरचना IDT_entry IDT; VOID IDT_INIT (शून्य) (अहस्ताक्षरित लंबा कीबोर्ड_पता; बिना हस्ताक्षरित लंबा आईडीट्रेस; बिना हस्ताक्षरित लंबा आईडीटी_पीटीआर; कीबोर्ड_एड्रेस = (अहस्ताक्षरित लंबा) कीबोर्ड_हैंडर; .OFSET_LWERBITS = कीबोर्ड_ADDRESS और 0XFFF; ; IDT.type_attr = 0x8e; /* INTERRUPT_G एटीई */आईडीटी.ऑफसेट_एड्रेस और 0xffff0000 >> 16; राइट_पोर्ट (0x21, 0x00); राइट_पोर्ट (0xA1, 0xff); आईडीटी_पीटीआर = (साइज़ऑफ़ (स्ट्रक्चर आईडीटी_साइज़)) ((idt_address & 0xffff)<< 16); idt_ptr = idt_address >> 16 ; लोड_आईडीटी(idt_ptr); )

IDT IDT_entry संरचनाओं की एक सरणी है। हम बाद में कीबोर्ड इंटरप्ट को हैंडलर से बाइंड करने पर चर्चा करेंगे, लेकिन अब देखते हैं कि PIC कैसे काम करता है।

आधुनिक x86 सिस्टम में दो PIC चिप्स होते हैं, प्रत्येक में आठ इनपुट लाइनें होती हैं। हम उन्हें PIC1 और PIC2 कहेंगे। PIC1 को IRQ0 से IRQ7 प्राप्त होता है, और PIC2 को IRQ8 से IRQ15 प्राप्त होता है। PIC1 कमांड के लिए पोर्ट 0x20 और डेटा के लिए 0x21 का उपयोग करता है, और PIC2 कमांड के लिए पोर्ट 0xA0 और डेटा के लिए 0xA1 का उपयोग करता है।

दोनों पीआईसी को आठ-बिट शब्दों के साथ आरंभ किया गया है जिन्हें इनिशियलाइज़ेशन कमांड वर्ड (आईसीडब्ल्यू) कहा जाता है।

संरक्षित मोड में, दोनों PIC को पहले इनिशियलाइज़ेशन कमांड ICW1 (0x11) जारी करने की आवश्यकता होती है। यह पीआईसी को डेटा पोर्ट पर तीन और इनिशियलाइज़ेशन शब्दों के आने की प्रतीक्षा करने के लिए कहता है।

ये आदेश PIC को पास करेंगे:

  • इंडेंट वेक्टर (ICW2),
  • PICs (ICW3) के बीच मास्टर/स्लेव संबंध क्या हैं,
  • पर्यावरण के बारे में अतिरिक्त जानकारी (ICW4)।

प्रत्येक PIC के इनपुट पर दूसरा इनिशियलाइज़ेशन कमांड (ICW2) भी भेजा जाता है। यह ऑफसेट निर्दिष्ट करता है, जो वह मान है जिसमें हम इंटरप्ट नंबर प्राप्त करने के लिए लाइन नंबर जोड़ते हैं।

पीआईसी अपने पिनों को एक-दूसरे के इनपुट में कैस्केड करने की अनुमति देते हैं। यह ICW3 का उपयोग करके किया जाता है और प्रत्येक बिट संबंधित IRQ के लिए कैस्केड स्थिति का प्रतिनिधित्व करता है। अब हम कैस्केडिंग पुनर्निर्देशन का उपयोग नहीं करेंगे और इसे शून्य पर सेट करेंगे।

ICW4 अतिरिक्त पर्यावरणीय पैरामीटर निर्दिष्ट करता है। हमें केवल निम्न बिट को परिभाषित करने की आवश्यकता है ताकि पीआईसी को पता चले कि हम 80x86 मोड में चल रहे हैं।

ता-डैम! PICs अब प्रारंभ हो गए हैं।

प्रत्येक पीआईसी में एक आंतरिक आठ-बिट रजिस्टर होता है जिसे इंटरप्ट मास्क रजिस्टर (आईएमआर) कहा जाता है। यह IRQ लाइनों का एक बिटमैप संग्रहीत करता है जो PIC पर जाता है। यदि बिट सेट है, तो PIC अनुरोध को अनदेखा कर देता है। इसका मतलब यह है कि हम संबंधित मान को 0 या 1 पर सेट करके एक विशिष्ट IRQ लाइन को सक्षम या अक्षम कर सकते हैं।

डेटा पोर्ट से पढ़ने पर आईएमआर रजिस्टर में मूल्य वापस आ जाता है, जबकि लिखने से रजिस्टर बदल जाता है। हमारे कोड में, PIC आरंभ करने के बाद, हम सभी बिट्स को एक पर सेट करते हैं, जो सभी IRQ लाइनों को निष्क्रिय कर देता है। बाद में हम उन लाइनों को सक्रिय करेंगे जो कीबोर्ड इंटरप्ट से मेल खाती हैं। लेकिन पहले, आइए इसे बंद करें!

यदि आईआरक्यू लाइनें काम कर रही हैं, तो हमारे पीआईसी आईआरक्यू पर सिग्नल प्राप्त कर सकते हैं और ऑफसेट जोड़कर उन्हें इंटरप्ट नंबर में बदल सकते हैं। हमें आईडीटी को इस तरह से भरना होगा कि कीबोर्ड से आने वाला इंटरप्ट नंबर उस हैंडलर फ़ंक्शन के पते से मेल खाए जिसे हम लिखेंगे।

आईडीटी में कीबोर्ड हैंडलर को बांधने के लिए हमें किस इंटरप्ट नंबर की आवश्यकता होगी?

कीबोर्ड IRQ1 का उपयोग करता है। यह इनपुट लाइन 1 है और PIC1 द्वारा संसाधित है। हमने PIC1 को ऑफसेट 0x20 के साथ आरंभ किया (ICW2 देखें)। इंटरप्ट नंबर प्राप्त करने के लिए, आपको 1 और 0x20 जोड़ने की आवश्यकता है, आपको 0x21 मिलता है। इसका मतलब है कि 0x21 को बाधित करने के लिए कीबोर्ड हैंडलर का पता IDT में बांध दिया जाएगा।

कार्य व्यवधान 0x21 के लिए आईडीटी भरने तक सीमित है। हम इस व्यवधान को कीबोर्ड_हैंडलर फ़ंक्शन में मैप करेंगे, जिसे हम असेंबली फ़ाइल में लिखेंगे।

IDT में प्रत्येक प्रविष्टि में 64 बिट्स होते हैं। इंटरप्ट से संबंधित प्रविष्टि में, हम हैंडलर फ़ंक्शन का संपूर्ण पता संग्रहीत नहीं करते हैं। इसके बजाय, हमने इसे दो 16-बिट टुकड़ों में विभाजित किया। निम्न-क्रम बिट्स को IDT प्रविष्टि के पहले 16 बिट्स में संग्रहीत किया जाता है, और उच्च-क्रम वाले 16 बिट्स को प्रविष्टि के अंतिम 16 बिट्स में संग्रहीत किया जाता है। यह सब 286 प्रोसेसर के साथ अनुकूलता के लिए किया जाता है। जैसा कि आप देख सकते हैं, इंटेल नियमित आधार पर और कई स्थानों पर इस तरह के नंबर तैयार करता है!

आईडीटी प्रविष्टि में, हमें केवल प्रकार पंजीकृत करना है, इस प्रकार यह संकेत मिलता है कि यह सब व्यवधान को पकड़ने के लिए किया जा रहा है। हमें कर्नेल कोड सेगमेंट का ऑफसेट भी सेट करना होगा। GRUB हमारे लिए GDT निर्धारित करता है। प्रत्येक जीडीटी प्रविष्टि 8 बाइट्स लंबी है, जहां कर्नेल कोड डिस्क्रिप्टर दूसरा खंड है, इसलिए इसका ऑफसेट 0x08 होगा (विवरण इस आलेख के दायरे से परे हैं)। इंटरप्ट गेट को 0x8e के रूप में दर्शाया गया है। बीच के शेष 8 बिट शून्य से भरे हुए हैं। इस तरह हम आईडीटी प्रविष्टि को पॉप्युलेट करेंगे जो कि कीबोर्ड इंटरप्ट से मेल खाती है।

एक बार जब हम आईडीटी मैपिंग का काम पूरा कर लेते हैं, तो हमें प्रोसेसर को यह बताना होगा कि आईडीटी कहां है। इसके लिए लिड्ट नामक एक असेंबली निर्देश है; इसमें एक ऑपरेंड लगता है। यह संरचना के एक वर्णनकर्ता का सूचक है जो आईडीटी का वर्णन करता है।

वर्णनकर्ता के साथ कोई कठिनाई नहीं है। इसमें बाइट्स में आईडीटी का आकार और उसका पता शामिल है। मैंने इसे और अधिक कॉम्पैक्ट बनाने के लिए एक सरणी का उपयोग किया। उसी तरह, आप एक स्ट्रक्चर का उपयोग करके एक डिस्क्रिप्टर भर सकते हैं।

Idr_ptr वेरिएबल में हमारे पास एक पॉइंटर होता है जिसे हम Load_idt() फ़ंक्शन में लिड निर्देश पर पास करते हैं।

लोड_आईडीटी: एमओवी ईडीएक्स, लिड्ट एसटीआई रेट

इसके अतिरिक्त, एसटीआई निर्देश का उपयोग करते समय लोड_आईडीटी () फ़ंक्शन एक रुकावट लौटाता है।

आईडीटी पॉप्युलेट और लोड होने के साथ, हम उस इंटरप्ट मास्क का उपयोग करके कीबोर्ड आईआरक्यू तक पहुंच सकते हैं जिसके बारे में हमने पहले बात की थी।

शून्य kb_init(शून्य) (write_port(0x21, 0xFD); )

0xFD 11111101 है - केवल IRQ1 (कीबोर्ड) सक्षम करें।

फ़ंक्शन - कीबोर्ड इंटरप्ट हैंडलर

इसलिए, हमने इंटरप्ट 0x21 के लिए एक आईडीटी प्रविष्टि बनाकर कीबोर्ड इंटरप्ट को कीबोर्ड_हैंडलर फ़ंक्शन में सफलतापूर्वक बाध्य कर दिया है। जब भी आप कोई बटन दबाएंगे तो यह फ़ंक्शन कॉल किया जाएगा।

कीबोर्ड_हैंडलर: कीबोर्ड_हैंडलर_मेन को iretd पर कॉल करें

यह फ़ंक्शन C में लिखे किसी अन्य फ़ंक्शन को कॉल करता है और iret क्लास निर्देशों का उपयोग करके नियंत्रण लौटाता है। हम अपना संपूर्ण हैंडलर यहां लिख सकते हैं, लेकिन C में कोड करना बहुत आसान है, तो चलिए वहां पर चलते हैं। जब नियंत्रण इंटरप्ट-हैंडलिंग फ़ंक्शन से बाधित प्रोग्राम में वापस आता है, तो रिट के बजाय iret/iretd निर्देशों का उपयोग किया जाना चाहिए। निर्देशों का यह वर्ग एक फ़्लैग रजिस्टर उठाता है, जिसे इंटरप्ट कॉल करने पर स्टैक पर धकेल दिया जाता है।

शून्य कीबोर्ड_हैंडलर_मेन(शून्य) (अहस्ताक्षरित चार स्थिति; चार कुंजीकोड; /* ईओआई लिखें */ राइट_पोर्ट(0x20, 0x20); स्थिति = रीड_पोर्ट(कीबोर्ड_स्टैटस_पोर्ट); /* यदि बफर खाली नहीं है तो निचली स्थिति बिट सेट की जाएगी */ अगर (स्थिति और 0x01) (कीकोड = read_port(KEYBOARD_DATA_PORT); अगर (कीकोड< 0) return; vidptr = keyboard_map; vidptr = 0x07; } }

यहां हम सबसे पहले PIC कमांड पोर्ट पर लिखकर एक EOI (एंड ऑफ इंटरप्ट) सिग्नल देते हैं। केवल तभी PIC आगे व्यवधान अनुरोधों की अनुमति देगा। हमें दो पोर्ट पढ़ने की जरूरत है: डेटा पोर्ट 0x60 और कमांड पोर्ट (उर्फ स्टेटस पोर्ट) 0x64।

सबसे पहले, हम स्थिति जानने के लिए पोर्ट 0x64 पढ़ते हैं। यदि स्थिति का निचला बिट शून्य है, तो बफ़र खाली है और पढ़ने के लिए कोई डेटा नहीं है। अन्य मामलों में हम डेटा पोर्ट 0x60 पढ़ सकते हैं। यह हमें दबायी गयी कुंजी का कोड देगा। प्रत्येक कोड एक बटन से मेल खाता है। हम कोड को संबंधित वर्णों में मैप करने के लिए keyboard_map.h में परिभाषित एक सरल वर्ण सरणी का उपयोग करते हैं। फिर प्रतीक को उसी तकनीक का उपयोग करके स्क्रीन पर प्रदर्शित किया जाता है जिसका उपयोग हमने कर्नेल के पहले संस्करण में किया था।

कोड को सरल रखने के लिए, मैं केवल a से z तक के लोअरकेस अक्षरों और 0 से 9 तक की संख्याओं को संसाधित करता हूं। आप आसानी से विशेष वर्ण, Alt, Shift और Caps Lock जोड़ सकते हैं। आप यह पता लगा सकते हैं कि कमांड पोर्ट के आउटपुट से कोई कुंजी दबाई गई थी या जारी की गई थी और उचित कार्रवाई कर सकते हैं। उसी तरह, आप किसी भी कीबोर्ड शॉर्टकट को शटडाउन जैसे विशेष कार्यों से जोड़ सकते हैं।

अब आप कर्नेल बना सकते हैं और इसे पहले भाग की तरह ही वास्तविक मशीन या एमुलेटर (क्यूईएमयू) पर चला सकते हैं।

x86 सिस्टम के लिए कर्नेल बनाने के लिए मार्गदर्शिका। भाग 1. बस मूल

आइए एक सरल कर्नेल लिखें जिसे x86 सिस्टम पर GRUB बूटलोडर का उपयोग करके बूट किया जा सकता है। यह कर्नेल स्क्रीन पर एक संदेश प्रदर्शित करेगा और प्रतीक्षा करेगा।

x86 सिस्टम कैसे बूट होता है?

इससे पहले कि हम कर्नेल लिखना शुरू करें, आइए समझें कि सिस्टम कैसे बूट होता है और कर्नेल पर नियंत्रण स्थानांतरित करता है।

अधिकांश प्रोसेसर रजिस्टरों में स्टार्टअप पर पहले से ही कुछ निश्चित मान होते हैं। निर्देशों के पते (इंस्ट्रक्शन पॉइंटर, ईआईपी) की ओर इशारा करने वाला रजिस्टर उस मेमोरी पते को संग्रहीत करता है जहां प्रोसेसर द्वारा निष्पादित निर्देश निहित है। डिफ़ॉल्ट EIP है 0xFFFFFFFF0. इस प्रकार, हार्डवेयर स्तर पर x86 प्रोसेसर 0xFFFFFF0 पते पर काम करना शुरू करते हैं। यह वास्तव में 32-बिट एड्रेस स्पेस के अंतिम 16 बाइट्स हैं। इस पते को रीसेट वेक्टर कहा जाता है।

अब चिपसेट मेमोरी मैप यह सुनिश्चित करता है कि 0xFFFFFFF0 BIOS के एक विशिष्ट भाग से संबंधित है, RAM से नहीं। इस समय, तेज़ पहुंच के लिए BIOS स्वयं को RAM में कॉपी कर लेता है। पता 0xFFFFFF0 में केवल मेमोरी में उस पते पर जाने का निर्देश होगा जहां BIOS की एक प्रति संग्रहीत है।

इस प्रकार BIOS कोड निष्पादित होना शुरू होता है। BIOS सबसे पहले एक ऐसे डिवाइस की तलाश करता है जो पूर्व निर्धारित क्रम में बूट हो सके। यह निर्धारित करने के लिए एक जादुई संख्या मांगी जाती है कि डिवाइस बूट करने योग्य है या नहीं (पहले सेक्टर के 511वें और 512वें बाइट्स के बराबर होना चाहिए) 0xAA55).

जब BIOS को एक बूट डिवाइस मिलती है, तो यह डिवाइस के पहले सेक्टर की सामग्री को भौतिक पते से शुरू करके रैम में कॉपी कर देता है 0x7c00; फिर पते पर जाता है और डाउनलोड किए गए कोड को निष्पादित करता है। इस कोड को कहा जाता है बूटलोडर.

बूटलोडर कर्नेल को एक भौतिक पते पर लोड करता है 0x100000. इस पते का उपयोग x86 सिस्टम पर सभी बड़े कर्नेल में शुरुआती पते के रूप में किया जाता है।

सभी x86 प्रोसेसर एक साधारण 16-बिट मोड में शुरू होते हैं जिसे कहा जाता है असली मोड. GRUB बूटलोडर मोड को 32-बिट पर स्विच करता है सुरक्षित प्रकार, रजिस्टर CR0 के निम्न बिट को सेट करना 1 . इस प्रकार, कर्नेल को 32-बिट संरक्षित मोड में लोड किया जाता है।

ध्यान दें कि लिनक्स कर्नेल के मामले में, GRUB लिनक्स बूट प्रोटोकॉल को देखता है और कर्नेल को वास्तविक मोड में बूट करता है। कर्नेल स्वचालित रूप से संरक्षित मोड में स्विच हो जाता है।

हमें क्या जरूरत है?

  • x86 कंप्यूटर;
  • लिनक्स;
  • एलडी (जीएनयू लिंकर);

असेंबलर में प्रवेश बिंदु सेट करना

आप कितना भी खुद को केवल C तक सीमित रखना चाहें, आपको असेंबलर में कुछ लिखना ही होगा। हम इस पर एक छोटी फ़ाइल लिखेंगे जो हमारे कर्नेल के लिए शुरुआती बिंदु के रूप में काम करेगी। यह केवल C में लिखे एक बाहरी फ़ंक्शन को कॉल करेगा और प्रोग्राम प्रवाह को रोक देगा।

हम यह कैसे सुनिश्चित कर सकते हैं कि यह कोड शुरुआती बिंदु है?

हम एक लिंकर स्क्रिप्ट का उपयोग करेंगे जो अंतिम निष्पादन योग्य फ़ाइल बनाने के लिए ऑब्जेक्ट फ़ाइलों को लिंक करती है। इस स्क्रिप्ट में हम स्पष्ट रूप से इंगित करेंगे कि हम 0x100000 पते पर डेटा लोड करना चाहते हैं।

यहाँ असेंबलर कोड है:

;;kernel.asm बिट्स 32;nasm निर्देश - 32 बिट सेक्शन .टेक्स्ट ग्लोबल स्टार्ट एक्सटर्न kmain;kmain को c फाइल स्टार्ट में परिभाषित किया गया है: cli;ब्लॉक इंटरप्ट mov esp, stack_space;स्टैक पॉइंटर कॉल kmain hlt सेट करें;CPU सेक्शन को रोकें .bss resb 8192; स्टैक स्टैक_स्पेस के लिए 8KB:

पहला निर्देश, बिट्स 32, x86 असेंबली निर्देश नहीं है। यह NASM असेंबलर के लिए एक निर्देश है जो 32-बिट मोड में काम करने वाले प्रोसेसर के लिए कोड जनरेशन निर्दिष्ट करता है। हमारे मामले में यह आवश्यक नहीं है, लेकिन आम तौर पर उपयोगी है।

कोड वाला अनुभाग दूसरी पंक्ति से शुरू होता है।

ग्लोबल एक और NASM निर्देश है जो स्रोत कोड प्रतीकों को वैश्विक बनाता है। इस तरह से लिंकर को पता चलता है कि प्रारंभ प्रतीक कहां है - हमारा प्रवेश बिंदु।

kmain एक फ़ंक्शन है जिसे कर्नेल.c फ़ाइल में परिभाषित किया जाएगा। बाहरी का अर्थ है कि फ़ंक्शन कहीं और घोषित किया गया है।

इसके बाद स्टार्ट फ़ंक्शन आता है, जो किमेन फ़ंक्शन को कॉल करता है और एचएलटी निर्देश के साथ प्रोसेसर को रोकता है। यही कारण है कि हम सीएलआई निर्देश का उपयोग करके पहले से ही व्यवधान को अक्षम कर देते हैं।

आदर्श रूप से, हमें कुछ मेमोरी आवंटित करने और इसे स्टैक पॉइंटर (एएसपी) के साथ इंगित करने की आवश्यकता है। हालाँकि, ऐसा लगता है कि GRUB ने पहले ही हमारे लिए यह कर दिया है। हालाँकि, आप अभी भी बीएसएस अनुभाग में कुछ स्थान आवंटित करेंगे और स्टैक पॉइंटर को इसकी शुरुआत में ले जाएंगे। हम resb निर्देश का उपयोग करते हैं, जो बाइट्स की निर्दिष्ट संख्या को सुरक्षित रखता है। Kmain को कॉल करने से तुरंत पहले, स्टैक पॉइंटर (esp) को mov निर्देश के साथ सही स्थान पर सेट किया जाता है।

सी में कर्नेल

कर्नेल.asm में हमने kmain() फ़ंक्शन को कॉल किया। इस प्रकार, हमारे "C" कोड को kmmain() के साथ निष्पादन शुरू करना चाहिए:

/* * कर्नेल.c */ void kmain(void) ( const char *str = "मेरा पहला कर्नेल"; char *vidptr = (char*)0xb8000; //वीडियो मेम यहां से शुरू होता है। unsigned int i = 0; unsigned int j = 0; /* यह लूप स्क्रीन को साफ़ करता है * 80 कॉलमों में से प्रत्येक में 25 पंक्तियाँ हैं; प्रत्येक तत्व 2 बाइट्स लेता है */ जबकि (j< 80 * 25 * 2) { /* blank character */ vidptr[j] = " "; /* attribute-byte - light grey on black screen */ vidptr = 0x07; j = j + 2; } j = 0; /* this loop writes the string to video memory */ while(str[j] != "\0") { /* the character"s ascii */ vidptr[i] = str[j]; /* attribute-byte: give character black bg and light grey fg */ vidptr = 0x07; ++j; i = i + 2; } return; }

हमारा कर्नेल केवल स्क्रीन साफ़ करेगा और "मेरा पहला कर्नेल" पंक्ति प्रदर्शित करेगा।

सबसे पहले हम एक vidptr पॉइंटर बनाते हैं जो पते की ओर इशारा करता है 0xb8000. संरक्षित मोड में, "वीडियो मेमोरी" इस पते से शुरू होती है। स्क्रीन पर टेक्स्ट प्रदर्शित करने के लिए, हम 0xb8000 से शुरू होकर 80 ASCII वर्णों की 25 पंक्तियाँ आरक्षित करते हैं।

प्रत्येक वर्ण को सामान्य 8 बिट्स द्वारा नहीं, बल्कि 16 द्वारा प्रदर्शित किया जाता है। पहला बाइट चरित्र को स्वयं संग्रहीत करता है, और दूसरा - विशेषता-बाइट। यह चरित्र के स्वरूपण, जैसे उसका रंग, का वर्णन करता है।

काले बैकग्राउंड पर हरे अक्षर s को प्रदर्शित करने के लिए, हम इस अक्षर को पहले बाइट में लिखते हैं और मान 0x02 दूसरे में लिखते हैं। 0 का अर्थ है काली पृष्ठभूमि, 2 का अर्थ है हरे टेक्स्ट का रंग।

यहाँ रंग चार्ट है:

0 - काला, 1 - नीला, 2 - हरा, 3 - सियान, 4 - लाल, 5 - मैजेंटा, 6 - भूरा, 7 - हल्का भूरा, 8 - गहरा भूरा, 9 - हल्का नीला, 10/ए - हल्का हरा, 11/बी - हल्का सियान, 12/सी - हल्का लाल, 13/डी - हल्का मैजेंटा, 14/ई - हल्का भूरा, 15/एफ - सफेद।

हमारे कर्नेल में हम काले रंग की पृष्ठभूमि पर हल्के भूरे रंग के टेक्स्ट का उपयोग करेंगे, इसलिए हमारी विशेषता बाइट का मान 0x07 होगा।

पहले लूप में, प्रोग्राम पूरे 80x25 ज़ोन पर एक खाली प्रतीक प्रिंट करता है। इससे स्क्रीन साफ़ हो जाएगी. अगले चक्र में, शून्य-समाप्त स्ट्रिंग "मेरा पहला कर्नेल" से 0x07 के बराबर विशेषता बाइट वाले अक्षर "वीडियो मेमोरी" में लिखे जाते हैं। यह स्ट्रिंग को स्क्रीन पर प्रिंट कर देगा।

जोड़ने वाला भाग

हमें NASM का उपयोग करके कर्नेल.asm को एक ऑब्जेक्ट फ़ाइल में असेंबल करने की आवश्यकता है; फिर कर्नेल.सी को किसी अन्य ऑब्जेक्ट फ़ाइल में संकलित करने के लिए जीसीसी का उपयोग करें। फिर उन्हें निष्पादन योग्य बूट कर्नेल से संलग्न करने की आवश्यकता होती है।

ऐसा करने के लिए, हम एक बाइंडिंग स्क्रिप्ट का उपयोग करेंगे, जिसे एक तर्क के रूप में ld को पास किया जाता है।

/* * link.ld */ OUTPUT_FORMAT(elf32-i386) ENTRY(start) अनुभाग ( . = 0x100000; .text: ( *(.text) ) .data: ( *(.data) ) .bss: ( *( .बीएसएस) ) )

पहले हम पूछेंगे आउटपुट स्वरूप 32-बिट निष्पादन योग्य और लिंक करने योग्य प्रारूप (ईएलएफ) के रूप में। ELF यूनिक्स x86 सिस्टम के लिए एक मानक बाइनरी फ़ाइल स्वरूप है। प्रवेशप्रतीक का नाम निर्दिष्ट करते हुए एक तर्क लेता है जो कि प्रवेश बिंदु है। वर्गों- यह सबसे महत्वपूर्ण हिस्सा है. यह हमारी निष्पादन योग्य फ़ाइल के मार्कअप को परिभाषित करता है। हम यह निर्धारित करते हैं कि विभिन्न अनुभागों को कैसे जोड़ा जाना चाहिए और उन्हें कहाँ रखा जाना चाहिए।

SECTIONS के बाद कोष्ठकों में, बिंदु (.) स्थिति काउंटर प्रदर्शित करता है, जो डिफ़ॉल्ट रूप से 0x0 है। इसे बदला जा सकता है, जो हम कर रहे हैं।

आइए निम्नलिखित पंक्ति को देखें: .text: ( *(.text) ) . तारांकन चिह्न (*) एक विशेष वर्ण है जो किसी भी फ़ाइल नाम से मेल खाता है। अभिव्यक्ति *(.text) का अर्थ है सभी इनपुट फ़ाइलों से सभी .text अनुभाग।

इस प्रकार, लिंकर ऑब्जेक्ट फ़ाइलों के सभी कोड अनुभागों को स्थिति काउंटर (0x100000) में पते पर निष्पादन योग्य फ़ाइल के एक अनुभाग में जोड़ता है। इसके बाद, काउंटर मान 0x100000 + परिणामी अनुभाग के आकार के बराबर होगा।

यही बात अन्य वर्गों के साथ भी होती है.

ग्रब और मल्टीबूट

अब सभी फ़ाइलें कर्नेल बनाने के लिए तैयार हैं। लेकिन अभी एक कदम और बाकी है.

नामक बूटलोडर का उपयोग करके x86 कोर लोड करने का एक मानक है मल्टीबूट विशिष्टता. GRUB हमारे कर्नेल को केवल तभी बूट करेगा यदि यह इन विशिष्टताओं को पूरा करता है।

उनके बाद, कर्नेल में पहले 8 किलोबाइट में एक हेडर होना चाहिए। इसके अतिरिक्त, इस हेडर में 3 फ़ील्ड होनी चाहिए, जो 4 बाइट्स हैं:

  • मैजिकलफ़ील्ड: जादुई संख्या शामिल है 0x1BADB002कोर की पहचान करने के लिए.
  • मैदान झंडे: हमें इसकी आवश्यकता नहीं है, आइए इसे शून्य पर सेट करें।
  • मैदान अंततः,: यदि आप इसे पिछले दो के साथ जोड़ते हैं, तो आपको शून्य प्राप्त होना चाहिए।

हमारा कर्नेल.एएसएम इस तरह दिखेगा:

;;kernel.asm ;nasm निर्देश - 32 बिट बिट्स 32 अनुभाग .पाठ; मल्टीबूट स्पेक एलाइन 4 dd 0x1BADB002 ;मैजिक dd 0x00 ;फ्लैग्स dd - (0x1BADB002 + 0x00) ;चेकसम। m+f+c शून्य वैश्विक प्रारंभ बाहरी kmain होना चाहिए; kmain को c फ़ाइल प्रारंभ में परिभाषित किया गया है: cli; ब्लॉक mov esp, stack_space को बाधित करता है; स्टैक पॉइंटर कॉल kmain hlt सेट करें; CPU अनुभाग को रोकें। bss resb 8192; स्टैक के लिए 8KB स्टैक_स्पेस:

कोर का निर्माण

अब हम कर्नेल.एएसएम और कर्नेल.सी से ऑब्जेक्ट फ़ाइलें बनाएंगे और उन्हें अपनी स्क्रिप्ट का उपयोग करके लिंक करेंगे।

नस्म -एफ एल्फ32 कर्नेल.एएसएम -ओ कास्म.ओ

यह लाइन ELF-32 प्रारूप में kasm.o ऑब्जेक्ट फ़ाइल बनाने के लिए असेंबलर को चलाएगी।

जीसीसी -एम32 -सी कर्नेल.सी -ओ केसी.ओ

"-सी" विकल्प यह सुनिश्चित करता है कि संकलन के बाद कोई छिपी हुई लिंकिंग न हो।

Ld -m elf_i386 -T link.ld -o कर्नेल kasm.o kc.o

यह हमारी स्क्रिप्ट के साथ लिंकर चलाएगा और एक निष्पादन योग्य नाम बनाएगा कर्नेल.

ग्रब सेट करना और कर्नेल प्रारंभ करना

पैटर्न कर्नेल को संतुष्ट करने के लिए GRUB को कर्नेल नाम की आवश्यकता होती है- . इसलिए कर्नेल का नाम बदलें. मैंने अपना नाम कर्नेल-701 रखा।

अब इसे डायरेक्टरी में डालें /गाड़ी की डिक्की. ऐसा करने के लिए आपको सुपरयूज़र अधिकारों की आवश्यकता होगी।

GRUB कॉन्फ़िगरेशन फ़ाइल grub.cfg में, निम्नलिखित जोड़ें:

शीर्षक myKernel रूट (hd0,0) कर्नेल /बूट/कर्नेल-701 ro

यदि छिपा हुआ मेनू निर्देश मौजूद है तो उसे हटाना न भूलें।

अपने कंप्यूटर को पुनरारंभ करें और आपको अपने सहित कर्नेल की एक सूची दिखाई देगी। इसे चुनें और आप देखेंगे:

यह आपका मूल है! आइए एक इनपुट/आउटपुट सिस्टम जोड़ें।

पी.एस.

  • किसी भी कर्नेल ट्रिक के लिए वर्चुअल मशीन का उपयोग करना बेहतर है।
  • कर्नेल को चलाने के लिए ग्रब2कॉन्फ़िगरेशन इस तरह दिखना चाहिए: मेनूएंट्री "कर्नेल 7001" (सेट रूट = "hd0,msdos1" मल्टीबूट / बूट / कर्नेल-7001 ro)
  • यदि आप क्यूमू एमुलेटर का उपयोग करना चाहते हैं, तो इसका उपयोग करें: क्यूमू-सिस्टम-आई386 -कर्नेल कर्नेल

विकीहाउ एक विकी की तरह काम करता है, जिसका अर्थ है कि हमारे कई लेख कई लेखकों द्वारा लिखे गए हैं। इस लेख के निर्माण के दौरान, गुमनाम सहित 90 लोगों ने इसे संपादित करने और सुधारने के लिए काम किया।

कोड की सैकड़ों-हजारों पंक्तियों से बना ऑपरेटिंग सिस्टम, उपयोगकर्ताओं को कंप्यूटर हार्डवेयर के साथ इंटरैक्ट करने की अनुमति देता है। वे आमतौर पर प्रोग्रामिंग भाषाओं C, C++ और असेंबली में लिखे जाते हैं।

कदम

    सबसे पहले, प्रोग्रामिंग सीखें।असेंबलर का ज्ञान आवश्यक है; सी जैसी अन्य अतिरिक्त निचले स्तर की प्रोग्रामिंग भाषाओं की समझ रखने की भी अत्यधिक अनुशंसा की जाती है।

    तय करें कि आप किस डिवाइस पर ऑपरेटिंग सिस्टम लोड करना चाहते हैं।यह एक सीडी, डीवीडी, फ्लैश मेमोरी डिवाइस, हार्ड ड्राइव या कोई अन्य कंप्यूटर हो सकता है।

    तय करें कि आप अपने ऑपरेटिंग सिस्टम को कैसा दिखाना चाहते हैं।क्या यह ग्राफिकल यूजर इंटरफेस (जीयूआई) के साथ एक पूर्ण ओएस होना चाहिए या शायद कुछ और न्यूनतर होना चाहिए? प्रक्रिया शुरू करने से पहले आपको यह जानना होगा कि किस दिशा में जाना है।

    जांचें कि आपका ऑपरेटिंग सिस्टम किस प्रोसेसर प्लेटफॉर्म को सपोर्ट करेगा।पर्सनल कंप्यूटर के लिए AI-32 और x86_64 दो सबसे आम संस्करण हैं, इसलिए उन्हें सबसे अच्छा विकल्प माना जा सकता है।

    तय करें कि क्या आप शुरुआत से ही सब कुछ स्वयं करना पसंद करते हैं, या क्या ऐसे कर्नेल हैं जिनके आधार पर आप सिस्टम पर निर्माण करना चाहेंगे। स्क्रैच से लिनक्स उन लोगों के लिए एक परियोजना है जो, उदाहरण के लिए, अपना स्वयं का लिनक्स वितरण बनाना चाहते हैं।

    चुनें कि आप अपने स्वयं के बूटलोडर का उपयोग करने जा रहे हैं या पूर्व-निर्मित ग्रैंड यूनिफाइड बूटलोडर (GRUB) का। क्योंकि आपके स्वयं के बूट प्रोग्राम को कोड करने के लिए कंप्यूटर हार्डवेयर और BIOS के व्यापक ज्ञान की आवश्यकता होती है, यह लाइव कर्नेल के लिए प्रोग्रामिंग शेड्यूल को पीछे धकेल सकता है।

    आप जिस प्रोग्रामिंग भाषा का उपयोग करने जा रहे हैं उसके बारे में निर्णय लें।बेशक, पास्कल या बेसिक जैसी भाषा में ओएस विकसित करना काफी संभव है, लेकिन इसे सी या असेंबली भाषा में लिखना बेहतर है। असेंबली भाषा नितांत आवश्यक है, क्योंकि ऑपरेटिंग सिस्टम के कुछ महत्वपूर्ण भागों के लिए इस विशेष भाषा के ज्ञान की आवश्यकता होती है। दूसरी ओर, C++ में OS के पूर्ण संस्करण को चलाने के लिए आवश्यक कीवर्ड शामिल हैं।

    • C या C++ कोड का उपयोग करके OS बनाने के लिए, आप निश्चित रूप से, एक कंपाइलर या दूसरे का उपयोग करेंगे। इसका मतलब यह है कि आपको चयनित सी/सी++ कंपाइलर के लिए मैनुअल/निर्देश/दस्तावेज़ीकरण अवश्य पढ़ना चाहिए जो सॉफ़्टवेयर के साथ आता है या वितरक की वेबसाइट पर उपलब्ध है। आपको कंपाइलर के बारे में बहुत सी जटिल बातें सीखनी होंगी, और C++ को बेहतर बनाने के लिए आपको इसका डिज़ाइन और ABI भी सीखना होगा। आपसे विभिन्न निष्पादन कार्य प्रारूपों (ईएलएफ, पीई, सीओएफएफ, नियमित बाइनरी, आदि) को समझने की उम्मीद की जाती है और ध्यान दें कि मूल विंडोज पीई प्रारूप (.exe) कॉपीराइट द्वारा संरक्षित है।
  1. एप्लिकेशन प्रोग्रामिंग इंटरफ़ेस (एपीआई) का चयन करें।अच्छे एपीआई का एक चयन POSIX है, क्योंकि यह अच्छी तरह से प्रलेखित है। सभी यूनिक्स सिस्टम में POSIX के लिए कम से कम आंशिक समर्थन होता है, इसलिए आपके ऑपरेटिंग सिस्टम पर यूनिक्स प्रोग्राम को बंडल करना मामूली होगा।

    एक डिज़ाइन पर निर्णय लें.मोनोलिथिक कर्नेल और माइक्रोकर्नेल हैं। मोनोलिथिक कर्नेल कर्नेल में सभी सेवाओं को चलाते हैं, जबकि माइक्रोकर्नेल में सेवाओं के कस्टम कार्यान्वयन के साथ एक छोटा कर्नेल होता है। सामान्य तौर पर, मोनोलिथिक कर्नेल तेज़ होते हैं, लेकिन माइक्रोकर्नेल में संभावित दोषों के विरुद्ध बेहतर अलगाव और सुरक्षा होती है।

    विकास और टीम वर्क पर विचार करें.इस तरह, आप बड़ी समस्याओं को सुलझाने में कम समय खर्च करेंगे, जिससे आप कम समय में एक बेहतर ऑपरेटिंग सिस्टम बना सकेंगे।

    अपनी हार्ड ड्राइव को पूरी तरह से न पोंछें.याद रखें, डिस्क को फ़ॉर्मेट करने से आपका सारा डेटा स्थायी रूप से साफ़ हो जाएगा! जब तक आपका संस्करण पूरी तरह कार्यात्मक रूप से तैयार न हो जाए, तब तक अपने कंप्यूटर को किसी अन्य OS से डुप्लिकेट बूट करने के लिए GRUB या किसी अन्य प्रबंधक का उपयोग करें।

    छोटा शुरू करो।मेमोरी प्रबंधन और मल्टीटास्किंग जैसे जटिल तत्वों पर आगे बढ़ने से पहले, छोटी चीज़ों पर ध्यान दें, जैसे टेक्स्ट डिस्प्ले और रुकावटें।

    नवीनतम कार्यशील संस्करण की एक बैकअप प्रति रखें।यदि आपके ओएस के वर्तमान संस्करण या उसके बाद के संस्करणों में कुछ भी पूरी तरह से गलत हो जाता है तो यह मानसिक शांति प्रदान करता है। यदि आपका कंप्यूटर खराब हो जाता है और बूट नहीं हो पाता है, जैसा कि आप स्वयं समझते हैं, तो काम करने के लिए दूसरी प्रति रखना एक उत्कृष्ट अवसर होगा, ताकि आप मौजूदा समस्याओं को ठीक कर सकें।

    वर्चुअल मशीन पर अपने नए ऑपरेटिंग सिस्टम का परीक्षण करें।हर बार जब आप परिवर्तन करते हैं या अपने उत्पादन कंप्यूटर से परीक्षण मशीन में फ़ाइलें स्थानांतरित करते हैं तो अपने कंप्यूटर को रीबूट करने के बजाय, आप वर्चुअल मशीन में ओएस चलाने के लिए एक एप्लिकेशन का उपयोग कर सकते हैं, जबकि आपका वर्तमान ओएस चलता रहता है। वीएम अनुप्रयोगों में वीएमवेयर (जिसमें एक स्वतंत्र रूप से उपलब्ध सर्वर भी है), वैकल्पिक ओपन सोर्स, बोच्स, माइक्रोसॉफ्ट वर्चुअल पीसी (लिनक्स के साथ संगत नहीं), और एक्सवीएम वर्चुअलबॉक्स शामिल हैं।

    एक रिलीज़ संस्करण जारी करें.यह उपयोगकर्ताओं को आपके ऑपरेटिंग सिस्टम में संभावित खामियों के बारे में बताने की अनुमति देगा।

  2. ऑपरेटिंग सिस्टम उपयोगकर्ता के अनुकूल भी होना चाहिए, इसलिए उपयोगी सुविधाओं को जोड़ना सुनिश्चित करें जो आपके डिज़ाइन का अभिन्न अंग बन जाएं।

    • एक बार विकास पूरा हो जाने पर, विचार करें कि क्या आप कोड को सार्वजनिक रूप से उपलब्ध कराना चाहते हैं या इसे निजी बनाना चाहते हैं।
    • यदि आप चाहते हैं कि आपका सिस्टम व्यवहार्य हो तो सुरक्षा सुविधाओं को अपनी सर्वोच्च प्राथमिकता बनाना सुनिश्चित करें।
    • प्रोग्राम सीखने के लक्ष्य के साथ एक ऑपरेटिंग सिस्टम डेवलपमेंट प्रोजेक्ट शुरू न करें। यदि आप सी, सी++, पास्कल, या किसी अन्य प्रासंगिक भाषा और सुविधाओं को नहीं जानते हैं, जिसमें पॉइंटर प्रकार, निम्न-स्तरीय बिट संचालन, बिट टॉगल, इनलाइन असेंबलर इत्यादि शामिल हैं, तो आप अभी तक तैयार नहीं हैं ओएस बनाने के लिए.
    • अपने स्वयं के ऑपरेटिंग सिस्टम को बेहतर बनाने में मदद के लिए OSDev और OSDever जैसे पोर्टल ब्राउज़ करें। कृपया विशेष रूप से ध्यान रखें कि अधिकांश मुद्दों के लिए, OSDev.org समुदाय यह पसंद करता है कि आप किसी फोरम में शामिल होने के बजाय स्वयं साइट सामग्री से परामर्श लें। यदि आप फिर भी मंच के सदस्यों की श्रेणी में शामिल होने का निर्णय लेते हैं, तो इसके लिए कुछ आवश्यक शर्तें होनी चाहिए। आपको C या C++ और x86 असेंबली लैंग्वेज का संपूर्ण ज्ञान होना चाहिए। आपको प्रोग्रामिंग में सामान्य और जटिल अवधारणाओं जैसे लिंक्ड सूचियाँ, कतारें आदि को भी समझना चाहिए। OSDev समुदाय अपने नियमों में स्पष्ट रूप से बताता है कि कोई भी नए प्रोग्रामर की देखभाल नहीं करेगा। यदि आप एक ओएस विकसित करने का प्रयास कर रहे हैं, तो यह कहने की आवश्यकता नहीं है कि आप एक प्रोग्रामिंग देवता हैं। आपके द्वारा चुने गए प्रोसेसर आर्किटेक्चर के लिए आपको प्रोसेसर मैनुअल भी पढ़ना आवश्यक है; उदाहरण के लिए x86 (इंटेल), एआरएम, एमआईपीएस, पीपीसी, आदि। प्रोसेसर संरचना पर ऐसी संदर्भ पुस्तक Google ("इंटेल मैनुअल", "एआरएम मैनुअल", आदि) पर खोजकर आसानी से पाई जा सकती है। स्पष्ट प्रश्न पूछने के लिए OSDev.org फोरम में शामिल न हों। इसके परिणामस्वरूप बस "फ़***इंग मैनुअल पढ़ें" जैसी प्रतिक्रियाएं मिलेंगी। सबसे पहले, आपको विकिपीडिया, उन विभिन्न उपकरणों के मैनुअल पढ़ने का प्रयास करना चाहिए जिनका आप उपयोग करने जा रहे हैं।
    • संभावित मृत स्थानों और अन्य त्रुटियों की जाँच करें। अंतराल, गतिरोध और अन्य समस्याएं आपके ऑपरेटिंग सिस्टम डिज़ाइन को प्रभावित कर सकती हैं।
    • यदि आप एक सरल विधि चाहते हैं, तो फेडोरा रिवाइजर, कस्टम निंबले एक्स, पपी रेमास्टर, PCLinuxOS mklivecd या SUSE स्टूडियो और SUSE कीवी जैसे लिनक्स वितरण के बारे में सोचें। हालाँकि, बनाया जा रहा OS उस कंपनी का है जिसने सबसे पहले यह सेवा शुरू की थी (हालाँकि आपके पास GPL के तहत इसे अपनी इच्छानुसार स्वतंत्र रूप से वितरित करने, बदलने और चलाने का अधिकार है)।
    • एक अच्छा समाधान यह होगा कि विकसित किए जा रहे ऑपरेटिंग सिस्टम के लिए एक पूरी तरह से नया विभाजन बनाया जाए।

    चेतावनियाँ

    • लापरवाही से ओएस को हार्ड ड्राइव पर कॉपी करने से यह पूरी तरह से क्षतिग्रस्त हो सकता है। ध्यान से
    • आपके पास दो सप्ताह में पूरी तरह से तैयार प्रणाली नहीं होगी। बूट करने योग्य ऑपरेटिंग सिस्टम से शुरुआत करें और फिर अधिक दिलचस्प चीज़ों की ओर बढ़ें।
    • यदि आप कुछ लापरवाही करते हैं जैसे यादृच्छिक I/O पोर्ट पर यादृच्छिक बाइट्स लिखते हैं, तो आप अपने ओएस को नष्ट कर देंगे और (सैद्धांतिक रूप से) आपके हार्डवेयर को ख़राब कर सकते हैं।
    • यह उम्मीद न करें कि गुणवत्तापूर्ण ऑपरेटिंग सिस्टम बनाना आसान होगा। कई जटिल अन्योन्याश्रयताएँ हैं। उदाहरण के लिए, ओएस को एकाधिक प्रोसेसर को संभालने में सक्षम बनाने के लिए, आपके मेमोरी मैनेजर में अतिरिक्त प्रोसेसर को एक ही समय में एक ही संसाधन तक पहुंचने से रोकने के लिए "लॉकिंग" तंत्र होना चाहिए। उपयोग किए गए "ब्लॉक" में यह सुनिश्चित करने के लिए एक शेड्यूलर शामिल होता है कि किसी भी समय केवल एक प्रोसेसर एक महत्वपूर्ण संसाधन तक पहुंच रहा है, जबकि अन्य सभी निष्क्रिय हैं। हालाँकि, शेड्यूलर का संचालन मेमोरी मैनेजर की उपस्थिति पर निर्भर करता है। यह गतिरोध निर्भरता का एक उदाहरण है. इस तरह की समस्याओं को हल करने का कोई मानक तरीका नहीं है; प्रत्येक ऑपरेटिंग सिस्टम निर्माता से अपेक्षा की जाती है कि वह अपने स्वयं के समाधान के साथ आने के लिए पर्याप्त कुशल हो।
क्या आपको लेख पसंद आया? अपने दोस्तों के साथ साझा करें!
क्या यह लेख सहायक था?
हाँ
नहीं
आपकी प्रतिक्रिया के लिए धन्यवाद!
कुछ ग़लत हो गया और आपका वोट नहीं गिना गया.
धन्यवाद। आपका संदेश भेज दिया गया है
पाठ में कोई त्रुटि मिली?
इसे चुनें, क्लिक करें Ctrl + Enterऔर हम सब कुछ ठीक कर देंगे!