Implementing a Simple Operating System — part 02

Himani Perera
4 min readOct 12, 2022

--

Hello everyone! Welcome to the second article of the DHP OS development article series. Last week, in the first article of this series, I demonstrated how to set up the development environment and boot our simple operating system. If you still haven’t gone through the previous article, please refer to the below mentioned link.

In this article, I’ll show you how to utilize C as the operating system’s programming language instead of assembly code.

Assembly is excellent for dealing with the CPU and provides complete control over all aspects of the code. However, C is a far more convenient language to use, at least for the authors. As a result, I’d prefer to use C as much as possible and assembly code only when necessary.

So, let’s get on to the steps.

Step 01: Setting Up a Stack

As all non-trivial C programs use a stack, one prerequisite for utilizing C is a stack. Setting up a stack is no more difficult than correctly aligning the esp register to the end of a free memory area.

The only things in memory so far are GRUB, BIOS, the OS kernel, and some memory mapped I/O. So, we can’t point the esp to a random section of memory since we don’t know if that memory space is available. Therefore, it is preferable to leave some uninitialized memory in the kernel’s ELF file’s bss section. We use bss section rather than the data section, to reduce the size of the OS executable. Since GRUB recognizes ELF, it will allocate any memory reserved in the bss section when the OS is loaded.

To declare uninitialized data, the NASM pseudo-instruction resb can be used.

Copy the below code into the file loader.s, right after the last definition (CHECKSUM).

Then add the following code to set up the stack pointer: This is done by pointing esp to the end of the kernel_stack memory.

Step 02: Calling C Code from Assembly

In this step, we need to call a C function using assembly code.

There are numerous conventions for calling C code from assembly code. Here, I’m using the cdecl calling convention.

In this cdeclconvention, the function’s arguments should be pushed onto the stack in a right-to-left order, with the rightmost argument being pushed first. And the return value is stored in the eax register.

Copy the code below into a new file called kmain.c. This will be the C code’s source file.

To achieve the task, put the following code after the esp instruction in the loader.s file.

Step 03: Compiling C code

Many flags for GCC must be used while compiling the C code for the OS. Because there is no standard library available for our operating system, the C code should not assume the availability of one. Moreover, we should turn on all the warnings and treat them as errors.

-m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector          -nostartfiles -nodefaultlibs -Wall -Wextra -Werror

Then we can call kmain function from loader.s by putting it in the file named kmain.c"at this stage, it will not take any arguments."

Step 04: Build Tools

Now we’ll set up some build tools to make compiling and testing the operating system easier. Although we used onemake, there are other different building systems available.

Create a file called Makefile and put the following text into it.

Now, Our working directory should now look like the below figure.

|-- bochsrc.txt
|-- iso
| |-- boot
| |-- grub
| |-- menu.lst
| |-- stage2_eltorito
|-- kmain.c
|-- loader.s
|-- Makefile

After all these modifications, our loader.s file should contain the following:

Now we should be able to start the operating system using the simple command make run and it will compile the kernel and boot it in Bochs.

Then you will get the following output.

Finally, quit the Bochs and use the command cat bochslog.txt to display the log it generated. If you can find the summation EAX = 000000006 (the sum of the arguments we provided), you are successful!

Final output (Number 6 on EAX register)

That’s all for this week. We were able to use the C language to further develop our operating system.

Let’s meet again next week with another exciting part of this article series. Until then, have a great week!

--

--

Himani Perera

Final Year Software Engineering Undergraduate at University of Kelaniya, Sri Lanka