Context
I tried to get into OSdev a long time ago back when i started learning x86 assembly, so as usual for someone who happens to be new i immediately jumped into fasm and started writing code.
I was also disappointed to say the least when i found out that when you write assembly code, you are either way bound to run c code instead because the operating system itself was written in C including syscalls.
and you can't really do much about it except if you actually ran the machine without an operating system, which was exactly what i did, and my initial expectations were that i had to first build an entire API and drivers just to print on the screen.
to my surprise it wasn't that, because Legacy bios has a library built in with each machine (at least for x86) that contains loads and loads of function calls that you could make (depends on the device you're working on ofc). there was only one tiny problem, i expected that i had a 64-bit processor so logically it would start in 64 bit right ?
well actually it starts up at 16-bit mode, well enjoy this article i hope it serves you well if you were planning on making your own operating system.
WHY (OSdev perspective)?
[disclaimer: I'm not a god, don't take everything below as very serious claims i might be wrong]
this was needed because there was some old software that ran on these systems which is hard coded to operate on them, and we can't really risk anything going wrong. this could be software and operating systems that were built a long time ago to idk.. operate a bank or a nuclear reactor.
but from a user's perspective i barely even give a shit about what happens there, why are they not running on their own specialized hardware anyways ? who would in their right mind buy an i9-13900h laptop to install a 16-bit or even a 32-bit operating system on it.
and also why wouldn't they just run some software virtualisation or translation layer and call it a day ? it just seems intuitive to me that it would be easier to build software for that than to keep all of this historical old stuff inside of a processor. of course i don't have much of a perspective on the matter so i can't really tell exactly the kind of problems that people face on the job.
well either way i had to accept the fact that i have to switch from 16-bit to 64-bit so that i could finally start working on my own operating system which i could built using whatever i want
if you go to this section of OSDev wiki, you would find out that they actually do not recommend building your own bootloader, instead they start up by the GNU bootloader then from that point onwards they get into the neat parts which is building the actual OS they also mentioned that you should have "at least 10 years of experience programming with multiple languages" (i wasn't even 6 months in xD suicide mission).
you could also take another route, UEFI => stands for unified extensible firmware interface. basically just something they built software-wise that would help you abstract away the route you'd have to go through with Legacy bios.
with legacy bios, you have to go through each step as in: - you have to be careful with the constrains like boot sector memory size (512 bytes). - you have and map the available memory on your system, and be very careful with jumps. - building your own filesystem with a reader for it. - jumping over from 16-bit to 32-bit (here you'll have to say goodbye to the bios-functions). - manually setting up paging if you want to move from 32-bit to 64-bit. - going through some historical left overs like and flipping random bits (i recommend you to read through it very carefully and understand every detail).
only then you get to finally load up your actual kernel.
another important note, x86 instruction sizes is not fixed which makes it so much more difficult to deal with in tight spaces, especially when you literally have 512 bytes only in the boot sector. this is why you would very often find:
xor ax, ax
instead of:
mov ax, 0
both are setting the 'ax' register to 0, but XOR takes up 2 bytes while MOV takes up 3 bytes.
all of this is only making the x86 architecture more and more strange, not to mention that in order to switch from different CPU modes.
you go through processes:
- enabling the A20 line
- building and loading the Global Descriptor Table
- setting up protected mode state
- check if the CPU supports long mode via CPUID
- having to check if CPUID is supported first
- building the page table
- enabling PAE in CR4
then some other steps until you do a final far jump into 64-bit code segment then load the kernel or do even some more startup work.
i also found a common issue which happens to be lack of resources usually when you are looking for resources related to x86 bare bones stuff, hardware specifics and maybe not just in x86 but in every other architecture its probably even worse because they are less popular, there really is no resources for this. you are most likely going to end up with learning resources that tell you "everything we have is outdated" or "don't expect us to carry you on like a tutorial, you'll have to carry your own weight on this"
especially considering that not many people are actually intereted in kernel development and embedded systems, and this lack of resources is making it even worse.
if you were starting a project similar to this, running bare bones or even making your own 32bit or 64bit operating system i would recommend some of these resources they might help you:
Videos/series:
- https://www.youtube.com/playlist?list=PLFjM7v6KGMpiH2G-kT781ByCNC_0pKpPN => this is a very good playlist, especially if you were planning to work with c.
- https://www.youtube.com/playlist?list=PL980gcR1LE3LBuWuSv2CL28HsfnpC4Qf7 => this one is fantastic, especially if you were building an OS in rust.
- https://youtu.be/t3iwBQg_Gik?si=M9gJz3eRD9_0eoBg => this one is also in c, especially if you want to work with UEFI.
- https://www.youtube.com/playlist?list=PL5GPYFCBKv4a_oDzW8d6BXMlTOZb34CUB => Falcon's series, this one is favorite and it also happens to be best if you work with zig.
- https://youtu.be/UMsscWnM67g?si=bqk-ZdD8bxdBngdK => something theoretical to think about, i would also advise looking at exokernels and real time operating systems, unikernels..., you might get some project ideas and at least you should know why many kernels exist and the different types.
- https://www.youtube.com/watch?v=9GDX-IyZ_C8 => same applies here, more theory.
other resources i found somewhat useful reading:
- https://wiki.osdev.org/Expanded_Main_Page => famous enough.
- https://github.com/mit-pdos/xv6-riscv
- https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
- https://www.ctyme.com/intr/int.htm
- https://github.com/intermezzos/kernel => just a hobby project, you'll actually find a lot of these in different languages, they are good for learning but i wouldn't recommend them if your goal was to build a 64-bit operating system you'd actually just waste your time for the most part because most of these are just simple toy fast operating systems that don't dare to go beyond x86 protected mode (32-bit). doesn't mean you shouldn't take a look, just don't expect much from them.
Conclusion:
OSdev needs to be revived and x86 needs to do some serious work on consumer grade hardware, maybe create variants or something because genuinely i don't think that many people care about 16-bit code.
i am yet to experience RISC-V and ARM based CPU's and try to create my own operating system on those, hopefully it goes well.