Write a Simple Operating System in Assembly!


Hello, it’s Codeinstein’s good friend Troy again, and today I will teach you how to write a VERY VERY simple operating system in the Assembly language.


What is Assembly Language?

Assembler (Assembly), is a low level programming language, which communicates usually directly to your computer itself, rather than the operating system. It is the basis of most applications and operating systems. Imagine it as an invisible language that your computer can better understand (And faster!) than high level languages such as (not only)  Java, C, or Swift. Most processors made by companies like Intel or AMD, include a recipe book within your CPU, which points out the meaning of each instruction. To read more on Assembly language, check out this Wikipedia article: https://en.wikipedia.org/wiki/Assembly_language


A simple tutorial!

So let’s get started with our simple OS Devving endeavors! Before we jump in the wagon on writing our little demo, I would like you to first understand what’s actually going to happen behind the scenes when running your operating system!


1.) You turn your computer on, usually with the on and off switch, or a simple button your press.

This in turn, brings you to the initialization of the BIOS, which stands for Basic Input/Output System. It is a very minimal amount of machine code, that checks that your computer is on and functional. Optionally, it will also check for the date and time with the CMOS chip, which is usually powered by a small battery to keep track of time even when the computer isn’t on or working.

2.) POST Check up.

POST is basically a diagnostic system which checks that all systems are running nominal, and your hardware is functioning properly.

3.) The paranormal search for the Magic Boot Number

After POST has completed, the BIOS checks for something called the Magic Boot Sector,  (AKA Magic Boot number), which is the entry point for execution of the operating system. It often is notated in hexadecimal, as 0xAA55 on AMD and Intel systems. It’s also the first 512 bytes of your OS, or hard disk. From here on we actually get to the fun stuff, which is our OS.

4.) The actual OS executes

So, as we go along, I will explain line by line each piece of code, and I recommend you write them into a file, preferably called boot.asm.


mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096

mov ax, 07C0h ; Set data segment to where we’re loaded
mov ds, ax

mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine

jmp $ ; Jump here – infinite loop!

text_string db ‘This is my own operating system from a Codeinstein tutorial’, 0

print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; int 10h ‘print char’ function

lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat


times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature



I won’t go through explain all of this, because the article should be kept short, but to understand this in short terms, basically you are creating a “stack”, which is a set space in RAM (Random Access Memory), where you are permitted to store any data you’d like, which will be later processed by the CPU. After you have created the stack, your operating system creates a “string”, which stores a message. In this case, “This is my own operating system from a Codeinstein tutorial”! Then, the string gets displayed on your monitor, because a loop is displaying the string character by character, until the loop ends, and the computer “halts”, meaning it just “freezes” until you restart your computer.


Now that you told me how to write this, how do I actually execute/use the OS?


First of all, you will need NASM, which turns your Assembly code into 1s and 0s for the computer to completely understand. If you use Linux:

Debian: sudo apt install nasm

CentOS: sudo yum install nasm

OpenSuSE: sudo zypper install nasm


Or in Windows, you download this executable: https://sourceforge.net/projects/nasm/

NOTE: On Windows 7/8/8.1/10, NASM is seen as a virus, because of it’s invalid signature. Do not worry though, I will assure you it isn’t a virus, and if it is, ask me and I will help you remove it, but the chances are highly unlikely that it even will be compromised.


Next, we actually compile it:

nasm -fbin boot.asm -o boot.bin


Same goes for Windows, except you may have to include the full path name, even if you are within the same directory.

For us good ol Linux users, once this piece of code has compiled, you will get a strange looking file called “boot.bin”. What you will do from here on, is insert a USB drive (Formated as FAT/FAT32), get it’s logical device number “/dev/sdb”, which most commonly works, and creating a nice little dd command to burn the OS on to it.

sudo dd if=boot.bin of=/dev/sdb1 && sync


Now you can reboot your computer, and boot OFF of the USB, which should show up with your awesome OS.


With windows it is probably way harder, for I have no clue on how you’d go on doing it on there, but I believe it would go along the lines of creating an ISO file which contains the newly compiled operating system.


I hope this tutorial was at least informative (if it didn’t work), and possibly has sparked a burning interest such it has with me, on developing an operating system. Thanks for reading!


Troy Sweeney

Linux kernel contributor, C/Java programmer, hacktivist. Spends most of his time helping others stay up to current with technology, security, and end to end encryption, he also has an addiction to German pastries.