How to implement your own operating system
HOW to Begin to Write an OS --------------------------- This Tutorial is Meant for Those Who Are Familiar with assembly languges and some knowledge of som . system internal Writing an Os is a challenging project The initial step of writing one is to code an efficient boot loader to load the kernel What happens when you boot a computer -..? The Bios is started first - It read the boot sector and loads it into the memory The boot sector is the first sector of the disk. A sector contain 512 bytes and that is the limitation to write our boot loader. So the boot loader must be at the most 512 bytes. So we must load the real . program or the kernel using the loader The boot sector is loaded at the physical address 0000: 7c00 and how does the Bios knows whether the disk has a valid bootsector The final two bytes of the bootsector ie; bytes 511 and 512 should be.? Aah and 55h Respectively. In Other Words, The Last Word in The Bootsector Should Be Aa55h. Tools Required: - NASM or Any Other Good Assem bler - Interrupt list like Ralf Brown's interrupt list -. PC Emulator like Bochs will help you and avoid frequent reboot of the system But this is not a compulsory requirement Now we will move into the coding part Let's start with a simple boot loader... **************************; a Simple bootloader-bl.ASM; ************* ************** ORG 0X7C00; BIOS LOADS OUR Loader At this Point Mov Si, Msg; Displays a Message on The ScreenCall DisplayStringmov AH, 0; Wait for Keyint 016h db 0eah; Machine Rebootdw 0000HDW 0FFFFh displaystring:; Function to display stringlodsbor al, aljz short finishmov ah, 0x0E; Echo a charmov bx, 0x0007int 0x10jmp displaystringfinish: retn msg db 'Press Any Key ...', 13, 10, 0 times 510 - ($ - $$) DB 0;
Fills the rest of the space except the last twotes with zerodw 0aa55h; magic word for a valid bootsector; ****************; The end; **************************************************************** NOW WE HAVE to Compile THIS PLAIN Binary. And the Write the bl.bin Into the bootsector Nasm bl.Aasm -f bin -o bl.bin you can use.. Even The bootsector. Even the Good debug.exe can also be used for what. C: /> debug bl.bin- WRITES BL.BIN INTO The Floppy Bootsector-Qc: /> Set The Defualt Boot To Floppy and Boot The Machine. if Are Using A Bochs Freedos Emulator, You Will Have To Do The Following Steps; - Edit File 'Bochsrc' And Chang Boot To 'A' IE; Boot: A- COPY THE BINARY FILE 'BL.BIN' INTO THE BOCHS DIRECTORY AND RENAME AS 'A. Img'- Run' Bochs.exe 'You Will See The Message 'Press Any Key ...' He ..... DID IHAR you Screaming in Joy? Yes, You Have Written A Successful Bootloader. This is not the end. The main purpose of a bootloader is not yet sattisfied. And W hat is it? You will have to load the kernel into the memory because a 512 bytes of code will not run a machine with all its power. The next step is to load a simple kernel into the memory. I have used many interrupt calls in the following example code. Each of them is properly commented. First of all we have to allocate stack for our program. Then load the kernel into any know address. I have loaded the kernel into 7c00h 512 for the simplicity of compiling the loader and Kernel in the Same Program. Before Winding We Have To Reset The Disk IE;
bringing the disk head to the track zero. This is same like seeking the file descriptor to beginning of the file. Then load the kernel into memory. And what mext? Ofcourse jump into the loaded kernel. So simple ... is not it? Try STUDYING THIS EXAMPLE CODE GIVEN BELOW.; *******************************; *****; ****** ************************************************************************************************************************** ***; Boot Loader by Fajib; This is the boot sector ... .; This will load the real os from the disk into the memory org 0x7c00 start :; setting the stack for loading the program climov ax, 0x9000mov ss, axmov sp, 0xffffsti mov [bootdrv], dl; dl contains the bootdisk name ie; dl = 0 if floppy a: / call load; function to load the kernel from disk into memory mov si, msgloadsuccess call putstr jmp loadkernel; I can directly jump into kernel Becoz i loading the kernel; AT 7C00 512; HANGS IF KERNEL NOT Loadoops: Mov Si, Msghangcall Putstrjmp Oops Retf; Loader Variables Bootdrv DB 0msgResetFail DB 'Disk Reset Failure!', 13, 10, 0 msg ResetSuccess DB 'Disk Reset Success ..., 13, 10, 0msgkernelload DB' Loading Kernel ..., 13, 10, 0msgloadsuccess DB 'Kernel Loaded Success, ..., 13, 10, 0 msghang db'. ', 0; Loader Functions Load :; we have to reset the disk before it move to the loaded program; say our real program is stored in sector 2; let's load it push ds; reset disk systemmov ax, 0; forces controller to recalibrate drive heads (seek to track 0 ) mov dl, [bootdrv] int 13hpop dsjc resetfail mov si, msgresetsuccesscall putstr mov ax, 0; loads sector into memorymov es, axmov ah, 2 mov al, 1;. loading 1 sector-kernel will be loaded Increase al for loading more MOV DX, 0MOV CX, 2; CH = Cylinder Number and Cl =
sector number 1-63 mov bx, 7e00h; 7e00h = 7c00h 512 ... loading my program here makes it easy for me int 13h; we can directly compile bootsector and kernel together in a single; program jc load; if fail then try to load it again mov si, msgkernelloadcall putstr retn resetfail: mov si, msgresetfailcall putstrretn putstr: lodsbor al, aljz short putstrdmov ah, 0x0Emov bx, 0x0007int 0x10jmp putstrputstrd: retn times 510 - ($ - $$) db 0; Filling the remaining free space In the sectordw 0AA55H; ***********************; ********* Boot loader **********; *********************************; ** **********************; ********** Start kernel ******** *******; *********************************; KERNEL Stored in Sector 2 Loadkernel: mov si, mymsgcall putstr call Console; Simple Console db 0EAh; machine rebootdw 0000hdw 0FFFFh mymsg db "Message from Fajib's Simple Kernel ...", 13, 10, 0 Console: mov si, msgconsolecall putstr mov si, promptcall putstr Waitkey: mov ah, 00h; Wait for Keyint 016h cmp al, 27; Check for ESC keyje Finish cmp al, 13; Check for ENTER keyje NewLine jmp EchoChar NewLine: mov si, promptcall putstrjmp Waitkey EchoChar: mov ah, 0x0E; Display the char with out attributemov bx, 0x0007int 10hjmp WaitkeyFinish: retn PROMPT DB 13, 10, 'C: />', 0msgconsole DB 13, 10, 'Console: Press Esc To Reboot', 13, 10, 0; *************** *****************; ********** * end kernel *************; **** *************************************** WOW! You Have Now Loaded a kernel successful ... But do not stop here ... Improvise Your Keernel AS Good possible ... Experimentation is the best learning method ... Do I inform me About your improvements and bus in my code to me at; email: fajib @