Important alert: (current site time 7/15/2013 6:25:47 PM EDT)
 

article

C++ Operating System Development

Email
Submitted on: 8/13/2003 7:32:15 AM
By: Steve von Takach  
Level: Advanced
User Rating: By 15 Users
Compatibility: C++ (general)
Views: 77612
(About the author)
 
     The aim of this tutorial is to show you how to write a developed kernel in C++. At this stage you should be fairly competent in the use of C++ and to have a little knowledge of how protected mode functions would be recommended. I’ll try my best to walk you through the more important parts of the code.

This article has accompanying files

 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
  1. You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
				


The aim of this tutorial is to show you how to write a developed kernel in C++. At this stage you should be fairly competent in the use of C++ and to have a little knowledge of how protected mode functions would be recommended. I’ll try my best to walk you through the more important parts of the code.

Part 1, Will look at the IDT (Interrupt Descriptor Table) and PIC (Programmable Interrupt Controller) and how to set these up.

Part 2, Will be programming the Keyboard Interrupt and how to develop a simple keyboard driver.

Part 3, Will walk through the development of a simple ‘std::cout’ and ‘std::cin’ implementation.

The end result will be a simple kernel that accepts input and processes it.
This :-

//--------------------Kernel.cpp--------------------
#include "iostream.h" //(cout, cin, endl)
#include "asmf.h" //(enable)

using std::cout; //so we only have to write cout.
using std::endl;
using std::cin;

int main(void)
{
char buffer[256]; //Max input from cin is 256 chars including '\0' char,
//This can change once we have ‘new’ and ‘delete’.
enable(); //Interrupts are disabled by my bootstrap.

cout << endl << "\nHello, what is your name? ";

cin >> buffer;

cout << "\nHi " << buffer <<"! Nice to meet you." << endl;
}

//--------------------Kernel.cpp--------------------

Introduction:
Let me start by saying that there are many ways of doing this. Some people use assembly, others dot the code with exorbitant inline assembly and others have assembly stubs for interrupts. Now I’m not a big believer in assembly but let’s be serious, assembly just makes things difficult, especially in C++ with name mangling and such. There are times where assembly will be our saviour, but for the most part we can do this in good old pure C++.

Back to Basics:
Ok. Where to start?.. Lets just start at the beginning. Interrupts. What are they? Well, when communicating to devices we use I/O ports. These ports enable us to retrieve information, request device operations and be informed of any status changes. The question is how do we know when there is information available? One option would be to poll the port, but that is very inefficient, the other would be to have the device interrupt us when there is information available, jump to some pre-determined code to handle the device and then return to what we were doing. Interrupts are also the ONLY way the CPU will communicate any errors it encounters.

Now the first thing to do when setting up the system to accept interrupts is to re-program the Programmable Interrupt Controller (also known as the PIC). This is because in real mode there are not as many CPU error interrupts (Intel has reserved the first 31 interrupts for the CPU. It is possible to use interrupts above 18 at the moment but this is not recommended as future CPU’s may use these interrupts) and to move all hardware interrupts out of the first 31 interrupts requires reprogramming the PIC: (View source, interrupt.h, for the definitions of PICM, ICW1 ect.)

void Interrupt::init_pic()
//re-programs the pic
{ //IRQ interrupts start at MASTER_VEC
outportb(PICM, ICW1);
outportb(PICS, ICW1);
outportb(PICMI, MASTER_VEC);
outportb(PICSI, SLAVE_VEC);
outportb(PICMI, 4);
outportb(PICSI, 2);
outportb(PICMI, ICW4);
outportb(PICSI, ICW4);
outportb(PICMI, 0xff);
outportb(PICSI, 0xff);
}


The next thing to do is to set up our Interrupt Descriptor Table. The IDT can be located anywhere in memory (unlike real mode) and it is up to the programmer to inform the CPU where to look for this table using the ‘LIDT’ instruction (This is where assembly comes into the picture). The IDT can be any length, but I would not recommend anything lower than space for at least 48 interrupts (CPU + IRQ) and the max is 256.

struct idt_gate
{
unsigned
short offset1;
unsigned
short selector;
unsigned
char dword_count;
unsigned
char type;
unsigned
short offset2;
} __attribute ((packed));

idt_gate idt[256];

The code above is the actual IDT. Each interrupt in the table must be set before it is loaded to prevent any errors. Offset 1 and 2 when placed together create a pointer to the handler’s code (offset1:offset2). Selector is the segment code selector that is used to access the code and the type of interrupt must be set. The type of handler is not very important in the kernel at the moment but must be set to either a trap (CPU interrupt) or interrupt gate, the type of code used in the interrupt (32bit), whether the interrupt is absent or present and the code permission level (eg Ring 3, but this doesn’t matter for embedded kernel drivers as they can access any kernel code on any level anyway).

Once the IDT has been set we must then create an IDT descriptor. This descriptor tells the CPU how many interrupts are available in the table and what its offset in memory is.

struct
{
unsigned
short size __attribute ((packed));
unsigned
long offset __attribute ((packed));
} idt_desc;

idt_desc.size=(256*8)-1;
idt_desc.offset=(unsigned long)idt;

Now all that is left to do is load the IDT descriptor for the CPU and we have control of interrupts!

asm("lidt %0" : "=m" (idt_desc)); //Load IDT.

That’s all! Pretty basic hey? You will have to write handlers for the CPU interrupts (at this stage a simple screen message, disabling of interrupt and a halt should do fine). For more information on CPU interrupts, check out:
http://member.netease.com/~laoyang/control/interrup.html

For more information on the PIC have a look at:
http://users.win.be/W0005997/GI/pic.html

The source code for a complete implementation of the code above is available on this page, and is in the interrupt.cpp, interrupt.h files.
Note:
/* Engesn (Derived) Operating System
* Copyright (c) 2002, 2003 Stephen von Takach

* All Rights Reserved.

*

* Permission to use, copy, modify and distribute this software

* is hereby granted, provided that both the copyright notice and

* this permission notice appear in all copies of the software,

* derivative works or modified versions.

*/

winzip iconDownload article

Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.Virus note:All files are scanned once-a-day by Planet Source Code for viruses, but new viruses come out every day, so no prevention program can catch 100% of them. For your own safety, please:
  1. Re-scan downloaded files using your personal virus checker before using it.
  2. NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.

If you don't have a virus scanner, you can get one at many places on the net including:McAfee.com

 
Terms of Agreement:   
By using this article, you agree to the following terms...   
  1. You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.


Other 1 submission(s) by this author

 


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this article (in the Advanced category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments

8/14/2003 9:28:43 PMLlama Boy

This is what i have been looking for, for a long time. I haven't for a toutorial so simple yet. Thanx!
(If this comment was disrespectful, please report it.)

 
8/15/2003 2:21:06 AM

nice one... can you also post code for process management,resource allocation management and stuff like that?...


temuchin
(If this comment was disrespectful, please report it.)

 
8/17/2003 9:27:57 AMJohannes Knapp

Is this a really OS ?

Can I use it without Windows/Linux ?

Who can I use it on a "empty"pc ? Without any OS ?
(If this comment was disrespectful, please report it.)

 
8/20/2003 2:22:18 AMSteve von Takach

Yes Johannes, it is an OS, and it can be used without Windows. It is only the kernel of the OS, and to make it boot you will need a bootstrap that sets up a protected mode environment before jumping to the OS code. The OS does everything else.
(If this comment was disrespectful, please report it.)

 
8/24/2003 8:53:07 AMJohannes Knapp

And how can I make a 'bootstrap that sets up a protected mode environment before jumping to the OS code' ??? I don`t know..., can YOU explain?
(If this comment was disrespectful, please report it.)

 
8/25/2003 3:23:16 AMSteve von Takach

The bootstrap is the first 512 bytes on any bootable device eg a floppy. This small area must include code that loads your OS (or a secondary loader). Bootstraps are not easy create but you can find one here: "http://my.execpc.com/~geezer/johnfine/" and download 'bootf02.zip' on that page. That should get the OS up and running. Have fun with it.
(If this comment was disrespectful, please report it.)

 
9/10/2003 6:19:18 AMSteve von Takach

Part 2 of this tutorial ~ The Keyboard Interrupt ~ is now avaliable Here: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=6743&lngWId=3

(If this comment was disrespectful, please report it.)

 
10/29/2003 8:43:39 PM Tyr

Awesome. Great example.
(If this comment was disrespectful, please report it.)

 
10/31/2003 10:00:13 AMhardik shah

a very good tutorial.congratulations from me.
(If this comment was disrespectful, please report it.)

 
11/4/2003 1:24:11 PMvivek patel

if u vote for this code.......than u will really enjoy my code...logon to http://www.vivekpatel.cjb.net anyway nice work and keep it up!!!!!!!!!!!!
(If this comment was disrespectful, please report it.)

 
6/22/2004 2:49:37 PM

struct idt_gate
{
unsigned short offset1;
unsigned short selector;
unsigned char dword_count;
unsigned char type;
unsigned short offset2;
} __attribute ((packed));

should be

typedef struct
{
unsigned short offset1;
unsigned short selector;
unsigned char dword_count;
unsigned char type;
unsigned short offset2;
} idt_gate __attribute ((packed));

or you'll get errors in:
idt_gate idt[256];

But nice tutorial! Setting idt with C... Cool! ;)
(If this comment was disrespectful, please report it.)

 
8/6/2004 6:54:33 AM

Amazing....
(If this comment was disrespectful, please report it.)

 
11/17/2004 10:15:18 AM

I keep getting "Invalid Opcode" when using this os
(If this comment was disrespectful, please report it.)

 
12/27/2004 6:09:31 PM

i have a request that someone make a EXTREMELY basic o.s. such as : just giving you a comand line and you being able to shut down or restart

i would be EXTREMELY happy if this happened...

well if this has happened someone point me to the link please!!!!
(If this comment was disrespectful, please report it.)

 
8/6/2006 4:57:57 AMJonathan

Great code, very useful for beginners like myself.
(If this comment was disrespectful, please report it.)

 
8/6/2006 4:58:41 AMJonathan

Great code, great for beginners' like myself
(If this comment was disrespectful, please report it.)

 
9/14/2006 1:46:08 PMJam

Is it possible to compile this code with MSVC6.0?
(If this comment was disrespectful, please report it.)

 
5/23/2007 4:05:58 AMPankaj

Great job man..!, I think it gives a better view to this topic.Thanks alot for sharing it with us.

Regards,
Pankaj
(If this comment was disrespectful, please report it.)

 
9/14/2007 2:14:46 PMWilliam

This will not compile! I get a lot of errors from DJGPP! Can't include Interupt.h (even though it exists, it says it doesn't!) and a lot of the flags are invalid that are run from build.bat

Can anyone help?
(If this comment was disrespectful, please report it.)

 
12/26/2007 4:22:04 PMChris

so you know you use assembly in this operating system, does the assembly create the bootstrap for the system, or do i have to make my own bootstrap?
(If this comment was disrespectful, please report it.)

 
6/4/2008 3:55:48 PMAmjafd

Hi to all its looking good but i have a error in build.bat and its as this
/////////////////////////////////////
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
'c:\nasm\nasmw' is not recognized as an internal or external command,
operable program or batch file.
c:/djgpp/bin/ld.exe: cannot find KStub.o
////////////////////////////////////
(If this comment was disrespectful, please report it.)

 
6/6/2008 3:58:16 AMAmjafd

yes William i am geting the same error
so what is the solution
(If this comment was disrespectful, please report it.)

 
12/21/2008 7:04:52 PMAzzimi

Thank you for this tutorial it helped me alot and now i understand a little more how Operating System works. I that you will make more tutorials.
(If this comment was disrespectful, please report it.)

 
4/4/2009 12:05:40 AMMicah

I am having problems with your kernel. I have a bootsector that I know works... so that's not the issue. When I run the OS the screen blacks out and the computer restarts. I have pinpointed the error to the line that calls the constructor in Support.c. Anybody have any help/advice?

thanks
(If this comment was disrespectful, please report it.)

 
8/23/2009 7:39:04 AMaustin

i was wondering if you could fix the above problem someone
/////////////////////////////////////
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
'c:\nasm\nasmw' is not recognized as an internal or external command,
operable program or batch file.
c:/djgpp/bin/ld.exe: cannot find KStub.o
////////////////////////////////////
ans send the whole file to me at austin.huntzinger@yahoo.com
(If this comment was disrespectful, please report it.)

 
3/16/2010 5:29:14 AMajmal

When I tried to run the build.bat, I am getting the following error:

gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
gcc.exe: environment variable DJGPP not defined
The system cannot find the path specified.
c:/djgpp/bin/ld.exe: cannot find KStub.o



Please help
(If this comment was disrespectful, please report it.)

 
6/13/2013 1:45:53 AMPravin

gcc.exe: environment variable DJGPP not defined
to solve this just download
http://www.osdever.net/downloads/compilers/DJGPP-Installer.exe
(If this comment was disrespectful, please report it.)

 
6/16/2013 11:55:40 AMreza

i want demo of operating system
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular article, please click here instead.)
 

To post feedback, first please login.