WRITING OPERATING SYSTEM USING C

Erandachamith
4 min readOct 12, 2022

--

This article is the second in a series that walks viewers through the creation of an x86 operating system. I described in the previous article how to construct the smallest OS that can be used with GRUB. Writing 0xCAFEBABE to the eax register was the sole action supported by that OS. Going back to the information below is advised if you feel lost.

This article will demonstrate how to program the OS employing C instead of assembly code. C is a far more client language for programmers to use, even though having assembly offers us the most control over every part of the code and is the greatest for engaging with the CPU.

Let’s begin the actual coding now!

welcome to coding!

Constructing a Stack
Developing a kernel stack is the initial step. A stack can be set very simply. The esp register just has to be directed to the last free memory block that is properly aligned. For optimal performance, aligning on block size is suggested here. Where should the esp point now is the question.

At first, just GRUB, BIOS, the OS kernel, as well as some memory-mapped I/O are present in the memory. Because we don’t know that whether memory space is available, we can’t direct the esp at a random place in memory.

As a result, we set aside a portion of uninitialized memory in the kernel’s ELF file’s bss section for our stack. To keep the OS executable shorter, the bss section is used in this instance as opposed to the data section.

The NASM pseudo-instructions RESB, RESW, RESD, RESQ, REST, RESO, RESY, and RESZ declare uninitialized storage space and are expected to be used in the BSS area of a module.

Here, the Kernel Stack size is specified using resb. Add the below code to your loader.s file to declare the stack.

And add the below code to set up the stack pointer. This is done by pointing esp to the end of the kernel_stack memory.

Now your loader.s file should look like below.

Calling Assembly Code From C
The following stage requires calling a C function from assembly code.

Make the kmain.c file in the C language first. and develop the kmain function. Keep the and arguments empty for the time being.

To call the C function use pseudo instruction extern to tell the assembler function is defined elsewhere. Add the below code to the loader.s file.

Then add the below code to the loader label to call the kmain function.

Compiling C Code
A lot of GCC flags must be utilized whenever building the C code for the OS as otherwise, the C code might suppose the existence of a source file.

In order to compile the C code, the following parameters must be used: -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs

Note that when building C programs, it is highly urged to enable all warnings and regard all signals as errors.

Build Tools
We employ the makes build system to simplify the process of compiling and verifying the OS.

Create the Makefile given below.

The contents of your working directory should now look like

The with short phrase create run, the OS will now be startable. The kernels will be generated as a result, and Bochs will begin.

Writing to EAX from C function
Have our C method return a result that will be input into the EAX by doing this now.

Let’s first update our kmain function so that it currently returns the sum of the three arguments that were sent to it.

Let’s also provide our kmain function with just some arguments. As it is the pattern used by GCC, we are using the cdecl calling convention in this situation. Furthermore, it specifies that (on x86) the arguments to a method shall be pushed on the stack in a right-to-left order.

The below image should be in your loader.s file.

Now when you boot up the QEMU and then display the log produced by Boch (using cat logQ.txt), you will find the summation EAX=6 written in it.

You can change the arguments pushed to the stack with any number and the summation will be written on EAX in hexadecimal. Below is the result of pushing 3,5, and 6.

I hope it was simpler for you to follow these instructions and that you gained knowledge about OS development using C as opposed to assembly code.

Thank you !

--

--