

Start your small operating system in Assembly - StylifyYourBlog
https://www.devimperium.com/tutorials/start_your_small_operating_system_in_assembly

======
danbaz
Writing the bootloader contrary to what exDM69 has said in my opinion is not a
waste of time. A few years back I set about writing the smallest possible
kernel I could for the x86 architecture and eventually got it down to 512
bytes - meaning the bootloader is the kernel.

[https://bitbucket.org/danielbarry/saxoperatingsystem/src](https://bitbucket.org/danielbarry/saxoperatingsystem/src)

Obviously in such a small amount of space, you only get an extremely simple
file system, use of one core, heavy reliance on interrupts, 16 BIT, no concept
of threads, ~16Kb of RAM and a lot of headaches. But the fact is that it works
and programs do get offered a variety of functions that they can go onto use
in order to save space. It's relatively complete, with a text editor, game and
simple script language. Without using interrupts, the speed is just
incredible. Unlike your normal kernel, there aren't a million pointers to
follow through or any safety checks eating up your precious processing time or
other processes to share your precious registers and cache. You may only use
one core, but you really do use that to your advantage.

In doing so, I learnt a lot about programming space efficiencies and OS design
in general. I would highly recommend it as a journey worth taking. It recently
all came in handy at work where I needed to run some very tight image
processing loops for 120FPS at HD (don't ask!) and knowing how the underlying
system worked meant I could bypass the heavy kernel operations in favour of my
own much leaner, purpose built ones.

UEFI has of course put a bit of a spanner in the works, where some modern
computers unless put into 'compatibility mode' in the 'BIOS', have completely
blocked out the world of hobby OS's for time being.

I would highly suggest that you all check out the MikeOS project and if you're
interested ask questions on the mailing list. It's a bit quiet at the moment
but he's a great guy and knows his stuff as well as the others on there.

What's more, if you consider yourself more hardcore and need more power, I
think the InfinityOS project was inspired by MikeOS and runs on 64 bit
computers and allows for distributed tasks over a network. It's very
impressive to say the least.

A down side to writing your own 32/64 Kernel is you take a look at the support
and what you're competing against and you start woundering whether you should
just use the embedded Linux kernel for example or of you're hell bent on ASM
then Kolibri OS is pretty complete!

Another point for 16 Bit kernels is the fact you get to whip your old machines
out of storage and boot those noisy beasts up. Load an old OS onto a kernel
and listen to it churn away.

~~~
101914
"...the speed is just incredible."

Others have suggested: Perhaps it seems "fast" only because the systems that
are considered acceptable today are (by comparison) incredibly slow.

"... purpose built..."

I believe it is only a minority of all my kernel's (and my OS's) capabilities
that I actually use. The majority are there only because it is too much work
to remove them. This is only my opinion.

~~~
jacquesm
No, it is fast, it runs entirely in the L1 cache. That's a huge boost compared
to anything that's larger than that. He's only going off-die to do IO.

~~~
101914
I am aware of that. Of course I am not using a kernel that fits in 512k, but
personally I prefer software that fits in 512k and I write and use such
software regularly.

But it still does not change the point of my comment.

One can either say a smaller, lighter system is "fast" or one can say a
larger, heavier system is "slow". It depends on the "benchmark" one chooses.

You characterize the performance of "small" software as a "huge boost".

While I might characterize the performance of a "large" software as a "huge
slowdown".

The difference is my benchmark is small software, not large software.

~~~
jacquesm
> I am aware of that.

That's nice, but that did not follow from your previous comment.

> Of course I am not using a kernel that fits in 512k, but personally I prefer
> software that fits in 512k and I write and use such software regularly. >
> But it still does not change the point of my comment. > One can either say a
> smaller, lighter system is "fast" or one can say a larger, heavier system is
> "slow". It depends on the "benchmark" one chooses. > You characterize the
> performance of "small" software as a "huge boost". > While I might
> characterize the performance of a "large" software as a "huge slowdown". >
> The difference is my benchmark is small software, not large software.

So, actually you seemed to agree with the OP then. Either that or you're not
making your point very effectively.

~~~
101914
Or you completely misunderstood my point.

I was not agreeing or disagreeing with the OP, nor with you. I was pointing
out that there is another way to look at the speed situation, besides the
obvious one.

Perhaps we could say that the way one sees the speed difference depends on
what speed one expects from the software one uses.

If one does not regularly use software that fits in 512k, then maybe one sees
the speed of such programs as a "huge boost".

But, if one is accustomed to using small executables that fit in 512k and one
does not regularly use software that is, e.g., 5, 10, 20m or more, then maybe
one sees having to use such larger software as a "huge slowdown".

------
exDM69
Nice little article, but the common wisdom in "hobby" OS development is: if
you want to write an operating system, do not write a bootloader.

The arcane details of initializing a x86 PC are not a good use of brain space
or programming time (things like A20 line). The OP says he spent _weeks_
writing this small snippet. There is some appeal in doing it "from the ground
up" in Assembly but that's very slow and tiresome. And there's still the PC
BIOS code blob running before your OS loads, so it's not like you're in
control of the CPU right from the first instruction it executes.

It takes roughly the same amount of trouble as this article (or slightly less)
to build a bootable ELF file using the Multiboot protocol, which you can boot
to using qemu or bochs directly (e.g. qemu -kernel mykernel.elf) or on real
hardware using GRUB.

There are lots of advantages to this: the bootloader will initialize the CPU
for you and you'll enter directly into 32 bit protected mode, the state of the
CPU will be in a well defined state. Additionally you can use the bootloader
to set up a graphics mode and provide a physical memory address to the VRAM
(this would require falling back to 16 bit mode for some BIOS interrupts and
then back to 32 bit mode).

You'll also get a proper ELF binary file with all the section information
(useful for setting up your page tables), and debugging symbols so you can
debug your kernel in GDB which is a lot more productive than using the built-
in monitor facilities of QEMU or Bochs. And you can actually use a linker so
you don't have to put all your code in one file (you will need a linker
script).

It also makes sense to boot to C code as soon as possible (Rust is another
option, C++ too but it's a bit more trouble). I actually did write a small OS
prototype in "raw" assembly (with interrupt handling and simple threading),
but it wasn't very productive and I quickly reverted to writing C code instead
and got a lot more done in less time.

You shouldn't need a lot of assembly code, only the early boot code (a few
hundred lines), the interrupt handler entry point and trampoline code for
booting the other cores of your CPU. In addition, there will be some inline
assembly oneliners for accessing privileged instructions (like lgdt, etc).

Here's the beginnings of my hobby OS project from years ago. I made the
mistake of using 64 bit long mode, which is a lot more work to get booted and
not a very good use of time. Stick to 32 bit mode if you want to get things
done.

[https://github.com/rikusalminen/danjeros](https://github.com/rikusalminen/danjeros)

~~~
JoshTriplett
As another alternative, bootstrap your OS using EFI. You get to boot directly
in 32-bit or 64-bit mode, as with multiboot, and you get a handful of OS-like
facilities to bootstrap yourself with, such as files, input, output, graphics,
and even networking. (You'll want to replace those with your own facilities
eventually, but until then you can focus on more interesting problems.)

~~~
pgeorgi
but you don't get to decide whether to use 32bit or 64bit mode, your firmware
does for you.

~~~
exDM69
Firmware? No, the OS will have to explicitly choose the mode the CPU operates
in.

The PC, under "normal" legacy BIOS, always boots to 16 bit mode (like in OP).
From there on, you manually have to change the processor operating mode to 32
bits (protected mode) or 64 bits (long mode), by setting some privileged
registers and doing a jump to 32/64 bit code.

In the case of UEFI, it may be possible to explicitly ask for a certain
operating mode at boot, but I am not familiar with that (yet).

~~~
JoshTriplett
> In the case of UEFI, it may be possible to explicitly ask for a certain
> operating mode at boot, but I am not familiar with that (yet).

That was the point of the comment you replied to. Normally, EFI either runs in
32-bit or 64-bit, and only loads and runs binaries for that mode.

------
ekr
This is in no way an operating system. An operating system (by most
definitions) is supposed to abstract the hardware, to provide things such as
processes, a scheduler, a file system, a framework for device drivers.

~~~
nawitus
The article describes how to start an operating system, not how to write it.
The article even states this at the end:

"Now, your job would be to develop your little kernel in the system.asm file.

~~~
ekr
This doesn't change the fact that the title is misleading.

~~~
jacquesm
Title seems fine to me. " _Start_ your small operating system in assembly".
That means it clearly is not advertised as an operating system in and of
itself.

