0% found this document useful (0 votes)
26 views14 pages

How To Develop An Operating System Using

This is all about how to create a OS i.e., Operating System using languages like C++ and C sharp. This is a expert created tutorial.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views14 pages

How To Develop An Operating System Using

This is all about how to create a OS i.e., Operating System using languages like C++ and C sharp. This is a expert created tutorial.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

How to develop an operating system using

C++?
Score: 3.9/5 (536 votes)

how operating systems are developed?


using C(or actually) C++, assembly and any programming languages like ada,
fortran, pascal you can develop your own operating system
but you have to use assembly in some places

an intruduction to assembly language


assembly is a low-level programming language that you can use it to control
everything like adding something to CPU registers, control the memory and
much more

how can i start to develop an operating system?


firstly, you have to know everything of your programming language like
pointers, functions (here i want to use C++)
secondly, you must have some knowledge of the assembly language

what tools i need to develop an operating system?


to develop an operating system you must have these:
1. an assembler
assembler takes your assembly code and give's you the low-level outputs like
an object containing your controls on CPU registers
the assembler here i want to use is nasm(netwide assembler)
you can download it from [Link]
2. a cross-compiler
in order to develop an operating system, you must have a cross compiler
because you must compile your kernel for it's executable format
here i use gcc(gnu compiler collection)
you can download it from [Link]
3. a linker
the linker take's your objects and link them to getter
here i use gnu binutils
you can download it from [Link]
4. a virtual machine
in order to test your operating system, you must have a vm(virtual machine)
but it isn't necessary
here i use virtualbox
you can download it from [Link]

notes before you get started


1. in developing an operating system, you cannot and cannot and cannot use
<iostream>, <fstream>, <memory>, <cstdio>, <cstdlib>, <windows.h>,
<unistd.h> and all the platform API's
you must create all of them yourself
2. you must very very be careful
when you are developing, you have control of everything
so, you can destroy one or some or all of your hardwares
in this case, i recommend to use a virtual machine to test your operating system
instead of rebooting more and more times

the bootloader
a bootloader is a bunch of code that is written in assembly language and must
be 512 byets(1 sector)
it load's your operating system's kernel
we skip this section and use grub as are bootloader
you can download grub source code from [Link]
or actually you maybe want a compiled for floppy: searching in google will
help you

a simple kernel
we want to develop an operating system
so, we have to create the functions ourselves
firstly, we create a file [Link] with these contents:
1 ;[Link]:the bootloader to boot are operating system with grub
2 [bits 32] ;we are in 32 bit
3 global start ;start's the operating system:we call it in the linker
4 script Edit &
5 extern _kernel_main ;this is in are .cpp file and it is the main function Run
6 of are kernel
7 ;do not modify these lines(these are needed by grub)!
8 section .mbHeader
9
10 align 0x4
11
12 ; setting up the Multiboot header - see GRUB docs for details
13 MODULEALIGN equ 1<<0 ; align loaded modules on page
14 boundaries
15 MEMINFO equ 1<<1 ; provide memory map
16 FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag'
17 field
18 MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader
19 find the header
20 CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
21
22 MultiBootHeader:
23 dd MAGIC
24 dd FLAGS
25 dd CHECKSUM

;you can modify these


start:
push ebx ;this is optional and load's the grub structure
call _kernel_main

now create a file: [Link] with these contents:


1 #include <stddef.h> //we can use it: it doesnt use any platform-related
2 api functions
3 #include <stdint.h> //include it to get int16_t and some integer types
4
5 /* Hardware text mode color constants. */
6 enum vga_color
7 {
8 COLOR_BLACK = 0,
9 COLOR_BLUE = 1,
10 COLOR_GREEN = 2,
11 COLOR_CYAN = 3,
12 COLOR_RED = 4,
13 COLOR_MAGENTA = 5,
14 COLOR_BROWN = 6,
15 COLOR_LIGHT_GREY = 7,
16 COLOR_DARK_GREY = 8,
Edit &
17 COLOR_LIGHT_BLUE = 9, Run
18 COLOR_LIGHT_GREEN = 10,
19 COLOR_LIGHT_CYAN = 11,
20 COLOR_LIGHT_RED = 12,
21 COLOR_LIGHT_MAGENTA = 13,
22 COLOR_LIGHT_BROWN = 14,
23 COLOR_WHITE = 15,
24 };
25
26 uint8_t make_color(enum vga_color fg, enum vga_color bg)
27 {
28 return fg | bg << 4;
29 }
30
31 uint16_t make_vgaentry(char c, uint8_t color)
32 {
33 uint16_t c16 = c;
34 uint16_t color16 = color;
35 return c16 | color16 << 8;
36 }
37
38 size_t strlen(const char* str)
39 {
40 size_t ret = 0;
41 while ( str[ret] != 0 )
42 ret++;
43 return ret;
44 }
45
46 static const size_t VGA_WIDTH = 80;
47 static const size_t VGA_HEIGHT = 24;
48
49 size_t terminal_row;
50 size_t terminal_column;
51 uint8_t terminal_color;
52 uint16_t* terminal_buffer;
53
54 void terminal_initialize()
55 {
56 terminal_row = 0;
57 terminal_column = 0;
58 terminal_color = make_color(COLOR_LIGHT_GREY, COLOR_BLACK);
59 terminal_buffer = (uint16_t*) 0xB8000;
60 for ( size_t y = 0; y < VGA_HEIGHT; y++ )
61 {
62 for ( size_t x = 0; x < VGA_WIDTH; x++ )
63 {
64 const size_t index = y * VGA_WIDTH + x;
65 terminal_buffer[index] = make_vgaentry(' ',
66 terminal_color);
67 }
68 }
69 }
70
71 void terminal_setcolor(uint8_t color)
72 {
73 terminal_color = color;
74 }
75
76 void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
77 {
78 const size_t index = y * VGA_WIDTH + x;
79 terminal_buffer[index] = make_vgaentry(c, color);
80 }
81
82 void terminal_putchar(char c)
83 {
84 terminal_putentryat(c, terminal_color, terminal_column,
85 terminal_row);
86 if ( ++terminal_column == VGA_WIDTH )
87 {
88 terminal_column = 0;
89 if ( ++terminal_row == VGA_HEIGHT )
90 {
91 terminal_row = 0;
92 }
93 }
94 }
95
96 void terminal_writestring(const char* data)
97 {
98 size_t datalen = strlen(data);
99 for ( size_t i = 0; i < datalen; i++ )
100 terminal_putchar(data[i]);
101 }
102
103 void kernel_main()
104 {
105 terminal_initialize();
terminal_writestring("wellcome to my first operating system!");
for(;;);
}

the linker script


create a file: [Link] with these contents:
1 /* The bootloader will look at this image and start execution at the symbol
2 designated as the entry point. */
3 ENTRY(start)
4
5 /* Tell where the various sections of the object files will be put in the final
6 kernel image. */
7 SECTIONS
8 {
9 /* Begin putting sections at 1 MiB, a conventional place for kernels
10 to be
11 loaded at by the bootloader. */
12 . = 1M;
13
14 /* First put the multiboot header, as it is required to be put very early
15 early in the image or the bootloader won't recognize the file format.
16 Next we'll put the .text section. */
17 .text BLOCK(4K) : ALIGN(4K)
18 {
19 *(.mbHeader)
20 *(.text)
21 }
22
23 /* Read-only data. */
24 .rodata BLOCK(4K) : ALIGN(4K)
25 {
26 *(.rodata)
27 }
28
29 /* Read-write data (initialized) */
30 .data BLOCK(4K) : ALIGN(4K)
31 {
32 *(.data)
33 }
34
35 /* Read-write data (uninitialized) and stack */
36 .bss BLOCK(4K) : ALIGN(4K)
37 {
38 *(COMMON)
39 *(.bss)
40 }
41
42 /* The compiler may produce other sections, by default it will put them
43 in
a segment with the same name. Simply add stuff here as needed. */
}

how to compile it
go to the shell (on windows cygwin is required):
type these commands:
1 nasm -f elf [Link] -o boot.o
2 g++ -c [Link] -o kernel.o -ffreestandinng -fno-exceptions -fno-rtti
3 gcc loader.o kernel.o -T [Link] -o kern -nostdlib -nodefaultlibs -lgcc

kingratulations!
your first operating system has been compiled successfully!
now you can create an image using grub-mkrescue:
create a directory: iso
in that directory, create another directory: boot then in the boot directory, create
a directory: grub and then create a file: [Link] with these contents(do not add
the braces in a new line) in the grub directory:
1 menuentry "myOS" {
2 multiboot /boot/kern
3}

then copy your kernel (kern) to iso/boot directory and run your shell again:
switch to the main directory of your kernel and type:
grub-mkrescue iso --output=[Link]

now you can boot and enjoy from your first operating system:: this simple
kernel without anything
Rate this
Please, choose stars to award:
(hover mouse and click)

C++

• Information
• Tutorials
• Reference
• Articles
• Forum

Articles

• Algorithms
• C++ 11
• Graphics and multimedia
• How-To
• Language Features
• Unix/Linux programming
• Source Code
• Standard Library
• Tips and Tricks
• Tools and Libraries
• Visual C++
• Windows API

Home page | Privacy policy


© [Link], 2000-2015 - All rights reserved - v3.1
Spotted an error? contact us

How to develop an operating system using


C++?
Score: 3.9/5 (536 votes)

how operating systems are developed?


using C(or actually) C++, assembly and any programming languages like ada,
fortran, pascal you can develop your own operating system
but you have to use assembly in some places

an intruduction to assembly language


assembly is a low-level programming language that you can use it to control
everything like adding something to CPU registers, control the memory and
much more

how can i start to develop an operating system?


firstly, you have to know everything of your programming language like
pointers, functions (here i want to use C++)
secondly, you must have some knowledge of the assembly language

what tools i need to develop an operating system?


to develop an operating system you must have these:
1. an assembler
assembler takes your assembly code and give's you the low-level outputs like
an object containing your controls on CPU registers
the assembler here i want to use is nasm(netwide assembler)
you can download it from [Link]
2. a cross-compiler
in order to develop an operating system, you must have a cross compiler
because you must compile your kernel for it's executable format
here i use gcc(gnu compiler collection)
you can download it from [Link]
3. a linker
the linker take's your objects and link them to getter
here i use gnu binutils
you can download it from [Link]
4. a virtual machine
in order to test your operating system, you must have a vm(virtual machine)
but it isn't necessary
here i use virtualbox
you can download it from [Link]

notes before you get started


1. in developing an operating system, you cannot and cannot and cannot use
<iostream>, <fstream>, <memory>, <cstdio>, <cstdlib>, <windows.h>,
<unistd.h> and all the platform API's
you must create all of them yourself
2. you must very very be careful
when you are developing, you have control of everything
so, you can destroy one or some or all of your hardwares
in this case, i recommend to use a virtual machine to test your operating system
instead of rebooting more and more times

the bootloader
a bootloader is a bunch of code that is written in assembly language and must
be 512 byets(1 sector)
it load's your operating system's kernel
we skip this section and use grub as are bootloader
you can download grub source code from [Link]
or actually you maybe want a compiled for floppy: searching in google will
help you

a simple kernel
we want to develop an operating system
so, we have to create the functions ourselves
firstly, we create a file [Link] with these contents:
1 ;[Link]:the bootloader to boot are operating system with grub
2 [bits 32] ;we are in 32 bit
3 global start ;start's the operating system:we call it in the linker
4 script
5 extern _kernel_main ;this is in are .cpp file and it is the main function
6 of are kernel
7 ;do not modify these lines(these are needed by grub)!
8 section .mbHeader
9
10 align 0x4
11 Edit &
12 ; setting up the Multiboot header - see GRUB docs for details Run
13 MODULEALIGN equ 1<<0 ; align loaded modules on page
14 boundaries
15 MEMINFO equ 1<<1 ; provide memory map
16 FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag'
17 field
18 MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader
19 find the header
20 CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
21
22 MultiBootHeader:
23 dd MAGIC
24 dd FLAGS
25 dd CHECKSUM

;you can modify these


start:
push ebx ;this is optional and load's the grub structure
call _kernel_main

now create a file: [Link] with these contents:


1 #include <stddef.h> //we can use it: it doesnt use any platform-related
2 api functions
3 #include <stdint.h> //include it to get int16_t and some integer types
4
5 /* Hardware text mode color constants. */
6 enum vga_color
7 {
8 COLOR_BLACK = 0,
9 COLOR_BLUE = 1,
10 COLOR_GREEN = 2,
11 COLOR_CYAN = 3,
12 COLOR_RED = 4,
13 COLOR_MAGENTA = 5,
14 COLOR_BROWN = 6,
15 COLOR_LIGHT_GREY = 7,
16 COLOR_DARK_GREY = 8,
17 COLOR_LIGHT_BLUE = 9,
18 COLOR_LIGHT_GREEN = 10,
19 COLOR_LIGHT_CYAN = 11,
20 COLOR_LIGHT_RED = 12,
21 COLOR_LIGHT_MAGENTA = 13,
22 COLOR_LIGHT_BROWN = 14,
23 COLOR_WHITE = 15,
Edit &
24 }; Run
25
26 uint8_t make_color(enum vga_color fg, enum vga_color bg)
27 {
28 return fg | bg << 4;
29 }
30
31 uint16_t make_vgaentry(char c, uint8_t color)
32 {
33 uint16_t c16 = c;
34 uint16_t color16 = color;
35 return c16 | color16 << 8;
36 }
37
38 size_t strlen(const char* str)
39 {
40 size_t ret = 0;
41 while ( str[ret] != 0 )
42 ret++;
43 return ret;
44 }
45
46 static const size_t VGA_WIDTH = 80;
47 static const size_t VGA_HEIGHT = 24;
48
49 size_t terminal_row;
50 size_t terminal_column;
51 uint8_t terminal_color;
52 uint16_t* terminal_buffer;
53
54 void terminal_initialize()
55 {
56 terminal_row = 0;
57 terminal_column = 0;
58 terminal_color = make_color(COLOR_LIGHT_GREY, COLOR_BLACK);
59 terminal_buffer = (uint16_t*) 0xB8000;
60 for ( size_t y = 0; y < VGA_HEIGHT; y++ )
61 {
62 for ( size_t x = 0; x < VGA_WIDTH; x++ )
63 {
64 const size_t index = y * VGA_WIDTH + x;
65 terminal_buffer[index] = make_vgaentry(' ',
66 terminal_color);
67 }
68 }
69 }
70
71 void terminal_setcolor(uint8_t color)
72 {
73 terminal_color = color;
74 }
75
76 void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
77 {
78 const size_t index = y * VGA_WIDTH + x;
79 terminal_buffer[index] = make_vgaentry(c, color);
80 }
81
82 void terminal_putchar(char c)
83 {
84 terminal_putentryat(c, terminal_color, terminal_column,
85 terminal_row);
86 if ( ++terminal_column == VGA_WIDTH )
87 {
88 terminal_column = 0;
89 if ( ++terminal_row == VGA_HEIGHT )
90 {
91 terminal_row = 0;
92 }
93 }
94 }
95
96 void terminal_writestring(const char* data)
97 {
98 size_t datalen = strlen(data);
99 for ( size_t i = 0; i < datalen; i++ )
100 terminal_putchar(data[i]);
101 }
102
103 void kernel_main()
104 {
105 terminal_initialize();
terminal_writestring("wellcome to my first operating system!");
for(;;);
}

the linker script


create a file: [Link] with these contents:
1 /* The bootloader will look at this image and start execution at the symbol
2 designated as the entry point. */
3 ENTRY(start)
4
5 /* Tell where the various sections of the object files will be put in the final
6 kernel image. */
7 SECTIONS
8 {
9 /* Begin putting sections at 1 MiB, a conventional place for kernels
10 to be
11 loaded at by the bootloader. */
12 . = 1M;
13
14 /* First put the multiboot header, as it is required to be put very early
15 early in the image or the bootloader won't recognize the file format.
16 Next we'll put the .text section. */
17 .text BLOCK(4K) : ALIGN(4K)
18 {
19 *(.mbHeader)
20 *(.text)
21 }
22
23 /* Read-only data. */
24 .rodata BLOCK(4K) : ALIGN(4K)
25 {
26 *(.rodata)
27 }
28
29 /* Read-write data (initialized) */
30 .data BLOCK(4K) : ALIGN(4K)
31 {
32 *(.data)
33 }
34
35 /* Read-write data (uninitialized) and stack */
36 .bss BLOCK(4K) : ALIGN(4K)
37 {
38 *(COMMON)
39 *(.bss)
40 }
41
42 /* The compiler may produce other sections, by default it will put them
43 in
a segment with the same name. Simply add stuff here as needed. */
}

how to compile it
go to the shell (on windows cygwin is required):
type these commands:
1 nasm -f elf [Link] -o boot.o
2 g++ -c [Link] -o kernel.o -ffreestandinng -fno-exceptions -fno-rtti
3 gcc loader.o kernel.o -T [Link] -o kern -nostdlib -nodefaultlibs -lgcc

kingratulations!
your first operating system has been compiled successfully!
now you can create an image using grub-mkrescue:
create a directory: iso
in that directory, create another directory: boot then in the boot directory, create
a directory: grub and then create a file: [Link] with these contents(do not add
the braces in a new line) in the grub directory:
1 menuentry "myOS" {
2 multiboot /boot/kern
3}

then copy your kernel (kern) to iso/boot directory and run your shell again:
switch to the main directory of your kernel and type:
grub-mkrescue iso --output=[Link]

now you can boot and enjoy from your first operating system:: this simple
kernel without anything
Rate this
Please, choose stars to award:

(hover mouse and click)

C++

• Information
• Tutorials
• Reference
• Articles
• Forum
Articles

• Algorithms
• C++ 11
• Graphics and multimedia
• How-To
• Language Features
• Unix/Linux programming
• Source Code
• Standard Library
• Tips and Tricks
• Tools and Libraries
• Visual C++
• Windows API

Home page | Privacy policy


© [Link], 2000-2015 - All rights reserved - v3.1
Spotted an error? contact us

Common questions

Powered by AI

When developing an operating system with C++, developers cannot use standard library headers like `<iostream>`, `<fstream>`, `<memory>`, etc., which are dependent on platform-specific APIs. Instead, they must create all required functions themselves to ensure the code is platform-independent and interacts directly with hardware .

The linker script specifies where the sections of the object files will be placed in the kernel image, starting typically at a conventional address like 1 MiB. It ensures that the multiboot header is placed at the beginning of the image and organizes text, data, and bss sections, thus allowing the kernel to be loaded correctly by the bootloader. It aligns sections properly in memory to prevent access errors and enables the loader to find necessary sections efficiently .

The terminal's functionality is implemented using a buffer located at a specific memory address (0xB8000), which represents the text mode frame buffer of the VGA. The `terminal_initialize` function sets up this buffer with default color entries, and various functions like `terminal_putentryat` and `terminal_putchar` manipulate the buffer to display characters on screen in the correct positions with specified colors. This approach directly interacts with the VGA hardware to render text output .

The bootloader is responsible for loading the operating system's kernel into memory when the computer starts. It is typically a small piece of code written in assembly language, sized to fit within a sector (512 bytes). The bootloader used in this context is GRUB, which loads the kernel for execution. The bootloader sets up the environment expected by the kernel and begins execution by calling the main function specified in the kernel's entry point .

Using a virtual machine is recommended because developing an operating system gives you control over the entire computer, and mistakes can easily lead to damage or malfunctions in the hardware. Testing on a virtual machine allows you to avoid rebooting your physical system repeatedly and provides a safe environment to test and debug your OS without risking hardware damage .

The `terminal_initialize` function in a simple kernel sets up the terminal display by initializing terminal rows, columns, and colors, and clearing the buffer. It prepares the terminal screen to display text output from the kernel by setting a default color and filling the buffer with blank entries in the default color .

The `make_vgaentry` function is significant because it combines a character and color information into a format that can be written to the VGA text buffer. This enables the kernel to display characters on the screen with specified foreground and background colors, facilitating text output in the terminal .

The essential tools needed to develop an operating system include an assembler, such as NASM, a cross-compiler like GCC, a linker from GNU Binutils, and optionally, a virtual machine for testing the operating system .

Standard APIs can't be used because they rely on services provided by an operating system, which doesn't exist yet when you're developing a new OS. This limitation is addressed by having developers write their own implementations of necessary functionalities that don't depend on existing OS services or APIs .

The multiboot header is critical in the kernel image because it allows the bootloader, such as GRUB, to recognize the file format and successfully load the OS. It includes fields like flags, magic numbers, and checksums to facilitate this process. Without the correct multiboot header, the bootloader may fail to load the kernel, preventing the operating system from starting .

You might also like