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.
Terms of Agreement:
By using this article, you agree to the following terms...
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.
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.
You may link to this article from another website, but ONLY if it is not wrapped in a frame.
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 :-
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.
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.)
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.
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.
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.
*/
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:
Re-scan downloaded files using your personal virus checker before using it.
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...
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.
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.
You may link to this article from another website, but ONLY if it is not wrapped in a frame.
You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)
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.)