Build your own operating system
Part 06
In this article, we are going to learn about how we can create a user mode to execute user programs, in contrast with kernel mode.
Let’s go…
There are two modes of operation in the operating systems. These are user mode and kernel mode.
User modes
The system is in user mode when the operating system is running a user application such as handling a text editor. The transition from user mode to kernel mode occurs when the application requests the help of operating system or an interrupt or a system call occurs.
This environment is less privileged than the kernel, and will prevent (badly written) user programs from messing with other programs or the kernel. Badly written kernels are free to mess up what they want.
Loading an external program
Normally we get external programs from drivers and file systems that enable them to load the software from a CD-ROM drive.
Instead of creating drivers, we will use a feature in GRUB called modules to load the program.
GRUB Modules
GRUB may load arbitrary files from the ISO image into memory, and these files are known as modules.
First, you have to edit the file iso/boot/grub/menu.lst.
Add the following segment at the end of the file in order to load the module to the GRUB.
module /modules/program
Now create the folder iso/modules.
To instruct GRUB how to load our modules, the “multiboot header” — the first bytes of the kernel — must be updated as follows.
; in file `loader.s`
MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant
ALIGN_MODULES equ 0x00000001 ; tell GRUB to align modules
; calculate the checksum (all options + checksum should equal 0)
CHECKSUM equ -(MAGIC_NUMBER + ALIGN_MODULES)
section .text: ; start of the text (code) section
align 4 ; the code must be 4 byte aligned
dd MAGIC_NUMBER ; write the magic number
dd ALIGN_MODULES ; write the align modules instruction
dd CHECKSUM ; write the checksum
Store following code segment inside the loader.s file.
Executing a simple program
Os can perform only a few steps at this stage. So we should write a simple program to execute. Store this file inside the modules folder.
; test module à copier dans iso/modules
; set eax to some distinguishable number, to read from the log afterwards
bits 32
start:
mov eax, 0xDEADBEEF
; enter infinite loop, nothing more to do
jmp start
As a result, a test program consisting of a very simple program that writes a value to a register suffices. Stopping Bochs after a while and checking the register for the proper number in the Bochs log will confirm that the program has been completed.
Compiling the program
Since our kernel cannot understand assembly language we have to compile the above code to binary. You can use the following command in terminal.
nasm -f bin program.s -o program
We must first locate the application in memory before proceeding. We can perform this totally in C if the contents of ebx are supplied as an argument to kmain.
In order to use arguments in kmain make a header file named multiboot.h.
Finally, we need to call the necessary functions within the “kmain” to run the simple program. So, you can do it like this.
Now we can run the OS using the “make run” command. If you succeed then you can see EAX=deadbeef in “bochslog.txt” like this.
Also, you can see the output of “com1.out” like this.
We have successfully started a program in our OS!
Thank you..