How To Make a Basic OS
How To Make a Basic OS
Introduction
In this tutorial, I will not teach you how to make a bunch of if statements in Python or Node.js or Java, but will teach you how to make a real OS, although it won't be able to do much. Basic experience with NASM x86 Assembly, but it is not required since this will explain everything needed along the way.
Installing Packages
To create an OS, you need two packages: NASM and QEMU. NASM is the Assembler we will use and QEMU is the VM we will use to run the OS.
You can use this basic Bash script to automatically download them if needed.
if ! which nasm > /dev/null; then install-pkg nasm; fi if ! which qemu-system-x86_64 > /dev/null; then install-pkg qemu; fi
Next up, you need to install the required libraries.
Installing Libraries
There are a number of libraries needed to run everything in QEMU. Thanks to @CSharpIsGud , this is fairly easy...
Using the following Bash script, you can install all of the required libraries.
mkdir libtmp; cd libtmp; wget https://repl.it/@CSharpIsGud/VolantOS.zip; unzip VolantOS; mv qemu/lib* ../; mv qemu/*.bin ../; mv qemu/*.rom ../; cd ..; rm -rf libtmp
You only need to run this once, so if you put it in your main.sh
file, you can comment it out after running once.
Setting Up The File System
Now, we need to set up the proper files for this all to work.
First, create a folder named iso
and inside that, create a folder named boot
. You also, in the root directory, need to create two files: Link.ld
and Loader.asm
. Link.ld
tells the linker how to put together the binary file so it can be used and Loader.asm
is your main Assembly code.
Setting Up The Linker File
Inside Link.ld
, put the following code:
ENTRY(entry) /* the name of the entry label */ SECTIONS { . = 0x00100000; /* the code should be loaded at 1 MB */ .text ALIGN (0x1000) : /* align at 4 KB */ { *(.text) /* all text sections from all files */ } .rodata ALIGN (0x1000) : /* align at 4 KB */ { *(.rodata*) /* all read-only data sections from all files */ } .data ALIGN (0x1000) : /* align at 4 KB */ { *(.data) /* all data sections from all files */ } .bss ALIGN (0x1000) : /* align at 4 KB */ { *(COMMON) /* all COMMON sections from all files */ *(.bss) /* all bss sections from all files */ } }
Of course, this is copied from @CSharpIsGud 's tutorial which was in turn copied from LittleOSBook, so I cannot really explain all of this that well.
The Assembly Template
To start working on your OS, you need to follow a basic template which makes the code bootable. Here is the template:
global entry MAGIC equ 0x1BADB002 ; These tell the bootloader that we are bootable FLAGS equ 0 SUM equ -MAGIC ; Now, setting up some basic constants to use in our program SYS_WRITE equ 4 SYS_READ equ 3 STDOUT equ 1 STDIN equ 2 SYS_EXIT equ 1 WRITESTART equ 0xB8000 ; Macros will go here section .data ; Nothing here for now... section .text: align 4 ; Align everything after this to a 4 byte boundary, which the boot header needs to be aligned to dd MAGIC ; dd means "define double word", a word is usually 2 bytes on most computers, so a dword is 4 bytes. You can think of a word as being a short in C and a dword being an int. dd FLAGS dd SUM entry: loop: jmp loop ; For now we won't do anything but loop forever.
This is just a basic template so that you can start writing your OS... Now, for the actual coding!
Making The OS
All of the code in this section will be done in the Loader.asm
file.
Declaring Variables
First off, in the .data
section, we need to set up a few variables. In the section, you should add the following code.
msg dd " HelloWorld OS 0.0.1 " ; Title message len equ $ - msg ; Get length msg2 dd "HelloWorld OS is a basic operating system that does nothing but print this text." ; Line 1 len2 equ $ - msg2 ; Get length msg3 dd 'HelloWorld OS is named after the common practice to make your first program simply say "Hello World".' ; Line 2 len3 equ $ - msg3 ; Get Length position dd 0 ; Required temp dd 0 ; Required templen dd 0 ; Required line dd 0 ; Required
All of the variables that have "Required" commented next to them are absolutely required for this. The other lines are messages to be printed and you can feel free to change them in any way you want.
Macros
Now, we need to create a few macros for this program to run!
Printing Characters
We need to have a way to print characters at a specified position. We can use a macro for that!
%macro printchar 2 ; The macro printchar will take 2 arguments mov eax, WRITESTART ; Set eax to the memory position of the start of text output mov ebx, [position] ; Now, we take the value of position and put it into ebx. add eax, ebx ; Now, we add ebx to eax to get the current memory position. mov ebx, %1 ; Now, we set ebx to the character we are printing. mov [eax], ebx ; And we set the given memory position to ebx to print the character. mov ecx, eax ; Now, we move eax to ecx for some more memory manipulation to set the color add ecx, 1 ; We increase ecx by 1 since we need to go to the next byte for the color data. mov edx, %2 ; Here, we set edx to the color we want. mov [ecx], edx ; And here we set the given memory position to edx to set the color. mov eax, [position] ; Lastly, these last 3 lines of the macro add 2 to the position variable. add eax, 2 mov [position], eax %endmacro
The comments explain how this works. Now, we need to be able to clear the screen.
Clearing the Screen
Now that we can print single characters, we need to be able to clear the screen! We need two macros for that!
First off, the macro to clear a given number of characters!
%macro clearscreen 1 ; The clearscreen macro takes 1 argument: the number of characters to clear. mov eax, %1 ; We move the number of characters to eax... mov [templen], eax ; ... and we use that to set templen. %%clearscreen: ; This label will be used for a loop. printchar ' ', 0 ; For each iteration of the loop, we print a space character with the default color, 0, to clear that character's position on the screen mov esi, [templen] ; Now, we need to move templen to esi... sub esi, 1 ; ..and subtract 1... mov [templen], esi ; ... and move that back to templen so we can decrement the variable. mov al, [templen] ; And now, we need to move templen to al so we can compare it. cmp al, 0 ; This checks if al (from templen) is 0. jne %%clearscreen ; If it is not 0, it iterates through the loop again. If it is 0, the macro ends. %endmacro
Once again, the comments explain this macro.
Now, we need to use this to clear the entire screen.
This is a crude way of doing it, but it works!
%macro clearall 0 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 clearscreen 4000 %endmacro
This just repeats the clearscreen
macro multiple times. Since the al
register is only a 8-bit register (at least I think... It might be 16-bit), there are limits to the amount it can go, so each 4000 doesn't actually clear 4000 digits.
This macro will be used for clearing the screen at the start of the program.
Printing Strings
Now, we need a macro to print strings.
%macro printstr 3 ; This takes 3 arguments, the string, the length, and the color. mov eax, %1 ; These two lines move the string to temp. mov [temp], eax mov eax, %2 ; And these move the length to templen. mov [templen], eax %%printstart: ; This is the start of a loop. mov esi, [temp] ; Here, we get the current character... mov esi, [esi] printchar esi, %3 ; ... and print it with the given color. mov esi, [temp] ; Now, we increment temp so we can get to the next character add esi, 1 mov [temp], esi mov esi, [templen] ; And we decrement templen... sub esi, 1 mov [templen], esi mov al, [templen] ; ... and compare it to 0 to see if we need to go through another iteration of the loop. cmp al, 0 jne %%printstart %endmacro
Moving Lines
Now, we need one last macro...
%macro gotoline 1 mov eax, %1 ; Move the line number to eax ... imul eax, 160 ; ... and multiply by 160 (characters per line) ... mov [position], eax ; ... and set the position to that. %endmacro
This macro will allow you to skip to certain lines.
Now that we have the macros, we can start programming the rest of the OS!
Programming the OS
Now that we have the macros, we need to use them in the .text
section.
Currently we have
entry: loop: jmp loop ; For now we won't do anything but loop forever.
but we will need to change this code.
The code for this basic OS is
entry: clearall ; Clear the screen mov eax, 0 ; Now, we need to reset the character position. mov [position], eax printstr msg, len, 0b00011010 ; Blue background, green text. gotoline 4 ; Go to line 4 printstr msg2, len2, 10 ; Green text gotoline 6 ; Go to line 6 printstr msg3, len3, 10 ; Green text loop: jmp loop ; For now we won't do anything but loop forever.
Of course, you can change things like the color, number of messages, order of messages, etc. This is just a basic OS like HelloWorld OS which can be found here: https://repl.it/talk/share/HelloWorld-OS/52435
Compiling and Running QEMU
To compile and run QEMU, you simply use the following Bash script:
nasm -f elf32 Loader.asm -o Loader.o ld -T Link.ld -melf_i386 Loader.o -o ./iso/boot/kernel qemu-system-x86_64 -kernel ./iso/boot/kernel
The next steps will be adding in C and then user input, so stay tuned to my next OSs and the tutorials for those next steps!
If you have any questions about this tutorial, please just ask!
Also, @DynamicSquid , here is a ping since you said you wanted this tutorial!
yay 800 cycle congrats
@HahaYes Thank you!
Can someone explain what this does?
@JosephSanthosh What do you mean exactly?
Like what is an OS, I'm a potato when it comes to coding. @AmazingMech2418
@JosephSanthosh An OS is what runs on the computer natively. Like think about Windows, Linux, or MacOS and how they don't run inside an environment and runs completely natively on the device.
OHhhhhhhh, that's a thing! @AmazingMech2418
@JosephSanthosh An operating system is a runtime environment with shared libraries.
@JosephSanthosh Yes, they are right, an OS is what a computer runs natively. For example, Windows, Linux, and MacOS are a few types of OSes.
@ZenoxHosting
Is that plural for OS?
Yay! This is going to be great
@HahaYes Thank you!
This is amazing! Thank you! I'm gonna have so much fun today!
@DynamicSquid Thank you and you're welcome! :D
@DynamicSquid I agree this is so much better than ALL the other OS tutorials on the internet!
@AverseABFun Thank you!
@AmazingMech2418 Yours shows how to install the packages while every other one does not also i want a ping for the next one.
@AverseABFun Thank you! And will do! :D I've been thinking about making the next one on AT&T Assembly, but am probably going to just make it on adding C. LOL!
@AmazingMech2418 if you do make another one, I would also like a ping :)
@DynamicSquid Will do! :D
@EpicGamer007 What? LOL! It's called word wrapping.
@AmazingMech2418 i know but that funny lol
@EpicGamer007 Ah. LOL!
Nice
@RyanGardiner1 Thank you!
Dude, could you ping me too? I learned from looking at the files and changed it up a bit. This s freaking awesome
@dabombdgdzjr Thank you! And sure!
I was messing around with it, then accidentally deleted a letter of code in the largest file. luckily it reloaded. then i went back there to search for a word, and it broke. the whole webpage. I went back on and ran it, but i lagged it up so much it couldnt reach the biggest file and i had to delete it XD @AmazingMech2418
please please PLEASE ping me when the next part comes out, you're a god!
@AmazingMech2418 can you ping me when the next part comes out?
@AmazingMech2418 Thanks! and thanks for the cycle too!
not working
@DiveshTheReal What do you mean?
@AmazingMech2418 Run and see it
@DiveshTheReal I just ran it and it worked...
@AmazingMech2418
i got stuck here
@DiveshTheReal That's all it does. LOL! Read the post. This doesn't include any input.
@AmazingMech2418 ok nvm them
@AmazingMech2418 any btw how do you install the firefox
@DiveshTheReal What do you mean?
Woah
So how would I add more to this OS? It would be nice to make it do something a little bit more complicated than to just make it say a certain sentence.
By the way, amazing tutorial! Keep it up!
@ZenoxHosting Thank you! I'm actually working on figuring out that kind of stuff myself now, so, hopefully, I'll be able to make the tutorial on that soon!
i want next tutorial
@nk1rwc It's coming soon!
Me waiting for the repl to load ...
Noice. I have a sudden urge to go make an OS... that runs a custom lang
@fuzzyastrocat Thank you!
@AmazingMech2418 Oh, one edit: I get the error "nasm: fatal: unable to open input file 'Loader.asm'
ld: cannot open linker script file Link.ld: No such file or directory", so I assume I'm actually supposed to write nasm -f elf32 ./iso/boot/Loader.asm -o Loader.o
and ld -T ./iso/boot/Link.ld -melf_i386 Loader.o -o ./iso/boot/kernel
?
Ok yep that worked, so maybe update that in tutorial?
@fuzzyastrocat Loader.asm
is in the root directory, right?
@AmazingMech2418 Oh no, I put loader.asm
and link.ld
in ./iso/boot, whoops ok
@fuzzyastrocat Oh! That makes sense then!
@AmazingMech2418 Thx for this tutorial, got my basic OS running — now to expand on it!
Perhaps add C?
@CodeLongAndPros That's what I'll figure out next and then make a tutorial for!
Imma have to try this out
As I said, I am so envious of low level lang devs.
it says this:
qemu-system-x86_64: error while loading shared libraries: libbrlapi.so.0.6: cannot open shared object file: No such file or directory
exit status 127
@toivocat Yeah, the binaries won't load for some reason due to an update to Repl.it.
how can I compile C to nasm? all tools i find (objconv, c2nasm) are for windows
Hey @AmazingMech2418, I'm getting an error saying there was an error while loading a shared library. Please help.
@JaydenSavarinat That happens to me too. It's an issue with Repl.it's storage system, so it won't save the file since it is a large binary file. I don't really know how to fix it though.
@AmazingMech2418 Oh, ok. Nice project though!
@JaydenSavarinat Thank you!
What language does this code uses??
@RevathyPurush Bash for the compiler script, but mostly NASM Assembly.
i wanna create a kernel here, i get this error: qemu-system-x86_64: error while loading shared libraries: libbrlapi.so.0.6: cannot open shared object file: No such file or directory
@zplusfour Did you add the library files?
@AmazingMech2418 oh I didn't
thank you for reminding me
An OS talks to hardware directly. I haven't looked at the code too closely but it only seems to be writing some text, how would you consider this an OS?
@maxina The text is through a raw memory buffer by the way. And this can run freestanding on a device, but I just used QEMU to emulate it.
@AmazingMech2418 ahh ok
I recommend explaining what 0xb8000 actually is and how the code works instead of just saying "here's the code, please copy it."
@programmeruser That's the memory location where the data on what gets printed on the screen starts...
@AmazingMech2418 I know that, I was saying that you should explain it in the tutorial...
Does this work on MacOS (64bit, Catalina)?
@LucasAllori No. Only Linux. You can create a VM though with like VMWare or VirtualBox!
@AmazingMech2418 I already have QEMU and NASM. My only issue is how to compile the stuff in that ELF format, since MacOS seems to not want to let me. Please tell me if there is any way to get it working on MacOS, so I don't have to make a VM. But if Linux is the only way then I will use it. (my mac is slow so VMs arent the best alternative)
Also, I have a rasberri pi with rasbianOS on it. Will that work for OSDEV?
@LucasAllori I'm pretty sure it has to be an x86 Linux device. You could make a VM, but I don't think it will work on a Mac. Macs are ARM I think anyways...
@AmazingMech2418 Macs are x86-64. I will now proceed to find myself a new laptop with Linux on it.
@AmazingMech2418 Actually nevermind, I just need to learn ARM assembly language
@LucasAllori You could probably dual-boot then!
@AmazingMech2418 Thats a good idea actually
It is now time for a 1 hour youtube session on how on earth you do that
thanks for your help though!
@LucasAllori If you use Ubuntu MATE, all you need is a flash drive or DVD drive and disk. It can get a little difficult with setting up BIOS and stuff, but it's not too hard...
@AmazingMech2418 @LucasAllori this does work on Linux. Just install the tools and it should work.
@programmeruser That's what I said. LOL!
@AmazingMech2418 I misread what you said. Anyways, I invited you to a repl with a link to free hacker.
@programmeruser I saw, but I already used that before, so it won't work again...
Um so I added more text variables, but dont know how to make it print them
@AmazingMech2418 can u answer?
@dabombdgdzjr You have to use the gotoline
and printstr
functions as defined. I explain these in the tutorial.
Wait, in which file @AmazingMech2418 cuz im blind XD i can never find what im looking straight at.
@dabombdgdzjr Loader.asm
in the printstr and gotoline places, I dont see it declaring a variable or calling it. @AmazingMech2418
@dabombdgdzjr You are looking in the macros. Look in the actual code of the program, starting at entry
.
@AmazingMech2418 it has this code:
html```
global entry
MAGIC equ 0x1BADB002 ; These tell the bootloader that we are bootable
FLAGS equ 0
SUM equ -MAGIC
SYS_WRITE equ 4
SYS_READ equ 3
STDOUT equ 1
STDIN equ 2
SYS_EXIT equ 1
WRITESTART equ 0xB8000
SCREEN_SIZE equ 12850
So would i edit sys.read to 4 to make it print more?
@dabombdgdzjr What is the "html" thing? Also, I mean in the entry
label, not where it is declared global in the memory. SYS_READ
is just a constant for an instruction.
@AmazingMech2418 sorry the html thing was me forgetting markdown XD. ok then, I have no idea, sorry for tha troubles
@dabombdgdzjr Look at line 107.
ah, thx u @AmazingMech2418
@dabombdgdzjr You're welcome!
Never turns on or starts or whatever @AmazingMech2418
@ridark What do you mean? It should start...
AmazingMech2418: In this tutorial, I will not teach you how to make a bunch of if statements in Python or Node.js or Java.
Me after creating MelnykOS: I am 2 parallel universes behind you.
Me after compiling my 32-Bit Edition Of Coresync OS: I am 48 parallel universes ahead of you.
@AJDevelopment dont punch me for using an old meme
WoW... @AmazingMech2418
Can you personally help @FluidCycling on his Repl
Because he is following your tutorial and got stuck on some error
https://repl.it/talk/ask/Hey-guys-I-just-started-devving-to-make-an-OS-but-it-has-an-error-called-exit-status1/53308
That's it.