Page 1 of 3

Language Made Just For Developing Kernels

Posted: Wed Oct 14, 2009 1:53 pm
by AaronMiller
I had an idea for a language that would be suited specifically towards the creation of kernels. It has a C styled syntax--with OOP functionality--and an MSVC styled way of writing in your assembly code. That is, at least in the theory of this language that does not yet exist. It's very C styled and has useful built-in functionality. (Such as _outb, _outw, _outl, _inb, _inw, _inl, _memcpy, _memset, _memcmp, etc.) Now, I know that pretty much does nothing that can't already be done in C--or in C with the help of assembly--but I think it's a pretty good idea. (Of course, I may be biased. :) ) Here's an incomplete example of a kernel that spouts out "Hello, World!" in the language. (When I was writing it I was setting it more towards initializing a GDT, the IDT, and handling exceptions as well... But I didn't quite get that far into the example.) I assume this is a perfectly reasonable place to post the idea. If not, I hope the topic will be moved to the right place.

Anyways, here's the example. "kernel.s" Excuse the tabbing of it.

Code: Select all

/* Setup */
// Specify the bits of the program
#pragma bits								32			// 32-bit program
#pragma org									0x100000	// go to 1st megabyte of memory

/* Defines */
// Multiboot information
#define MBOOT_MAGIC							0x1BADB002
#define MBOOT_PAGE_ALIGN					1<<0
#define MBOOT_MEM_INFO						1<<1
#define MBOOT_FLAGS							MBOOT_PAGE_ALIGN|MBOOT_MEM_INFO
#define MBOOT_CHECKSUM						-(MBOOT_MAGIC+MBOOT_FLAGS)

/* Macros */
// Bit Management
#define Bits8To16(a,b)						((u16)(((u8)(a))|(((u16)((u8)(b)))<<8)))
#define Bits16To32(a,b)						((u32)(((u16)(a))|(((u32)((u16)(b)))<<16)))
#define Bits8To32(a,b,c,d)					(Bits16To32(Bits8To16(a,b),Bits8To16(c,d)))
#define Bits32To16L(a)						((u16)((u32)(a)))
#define Bits32To16H(a)						((u16)(((u32)(a)>>16)&0xFFFF))
#define Bits16To8L(a)						((u8)(a))
#define Bits16To8H(a)						((u8)(((u16)(a)>>8)&0xFF))
#define Bits32To8LL(a)						(Bits16To8L(Bits32To16L(a)))
#define Bits32To8LH(a)						(Bits16To8L(Bits32To16H(a)))
#define Bits32To8HL(a)						(Bits16To8H(Bits32To16L(a)))
#define Bits32To8HH(a)						(Bits16To8H(Bits32To16H(a)))
// Bit Management (Windows Equivalents)
#define LOWORD(a)							(Bits32To16L(a))
#define HIWORD(a)							(Bits32To16H(a))
#define LOBYTE(a)							(Bits16To8L(a))
#define HIBYTE(a)							(Bits16To8H(a))
// Flags & Bits
#define MakeFlag(id)						(((u32)1)<<(id))
#define ClearBit(value,bit)					(value &= ~(1<<bit))
#define SetBit(value,bit)					(value |= (1<<bit))
#define GetBit(value,bit)					(value & (1<<bit))

/* Packed Types */
// GDT Entry
type	GDT_ENTRY
{
	u16										limitLow;
	u16										baseLow;
	u8										baseMiddle;
	u8										access;
	u8										granularity;
	u8										baseHigh;
} packed(1);
// GDT Pointer
type	GDT_PTR
{
	u16										limit;
	u32										base;
} packed(1);
// Task State Segment
type	TSS_ENTRY
{
	u32										prevTss;
	u32										esp0;
	u32										ss0;
	u32										esp1;
	u32										ss1;
	u32										esp2;
	u32										ss2;
	u32										cr3;
	u32										eip;
	u32										eflags;
	u32										eax;
	u32										ecx;
	u32										edx;
	u32										ebx;
	u32										esp;
	u32										ebp;
	u32										esi;
	u32										edi;
	u32										es;
	u32										cs;
	u32										ss;
	u32										ds;
	u32										fs;
	u32										gs;
	u32										ldt;
	u16										trap;
	u16										ioMapBase;
} packed(1);
// Screen character
type	TEXTMODE_CHAR
{
	u8										c;	// Character
	u8										a;	// Attribute
} packed(1);								// pack down to the byte

/* Variables */
// From the linker script
extern	u32									code;
extern	u32									bss;
extern	u32									end;
// Reserved data. (This will go in the .bss section)
reserve	u8									_kernelStack[8192];	// Allocate space for the kernel's stack

/* Program Entries */
// Data for the very start of the program
__head
{
	/*
		This information will appear at the very beginning of the file's .text
		section. The dd() function simply writes a dword to the file as data.
		It is recommended that you do NOT call this function 
	*/
	mboot:
		// Required values of the multiboot header
		dd(MBOOT_MAGIC);
		dd(MBOOT_FLAGS);
		dd(MBOOT_CHECKSUM);
		// Information
		dd($mboot);		// mboot is a label, but we're treating it as a variable
		dd($code);
		dd($bss);
		dd($end);
		dd($start);		// start is a function, but we're treating it as a variable
		// Video
		dd(0); //mode
		dd(0); //width
		dd(0); //height
		dd(0); //depth
}

/* Functions */
// Start of the program
nakedfunction start()
{
	// Handle the inline assembly
	asm
	{
		// Setup the stack
		mov		esp,	$_kernelStack
		// Push the data to the header
		push	ebx		// boot params
		push	eax		// 0x2BADB002
		// Stop interrupts
		cli
		// Call the main function
		call	$kmain
		// If we reach this point... STOP
		cli
		hlt
	}
}
// Flush the TSS
fastfunction tssFlush()
{
	asm
	{
		mov		ax, 0x2B
		ltr		ax
	}
}
// Set a GDT gate
fastfunction gdtSetGate(u32 index, u32 base, u32 limit, u8 access, u8 granularity)
{
	// Set the base address
	$g_gdtEnt[$index].baseLow		= (u16)($base&0xFFFF);
	$g_gdtEnt[$index].baseMiddle	= (u8)(($base>>16)&0xFF);
	$g_gdtEnt[$index].baseHigh		= (u8)(($base>>24)&0xFF);
	// Set the access flag
	$g_gdtEnt[$index].access		= $access;
	// Set the limit and granularity
	$g_gdtEnt[$index].limitLow		= (u16)($limit&0xFFFF);
	$g_gdtEnt[$index].granularity	= (u8)((($limit>>16)&0x0F)|($granularity&0xF0));
}
// Write the TSS
fastfunction gdtSetTss(u32 index, u16 ss0, u32 esp0)
{
	// Preliminary
	u32 base, limit;
	// Calculate the base and limit
	$base = (u32)@g_tssEnt;
	$limit = $base+sizeof(TSS_ENTRY);
	// Add the TSS to the GDT
	gdtSetGate($index, $base, $limit, 0xE9, 0x00);
	// Zero out the TSS
	kMemSet((u8 *)@g_tssEnt, 0, sizeof(TSS_ENTRY));
	// Setup the stack segment/pointer
	$g_tssEnt.ss0 = $ss0;
	$g_tssEnt.esp0 = $esp0;
	// Set all the segments
	$g_tssEnt.cs = 0x0B;
	$g_tssEnt.ss = 0x13;
	$g_tssEnt.ds = 0x13;
	$g_tssEnt.es = 0x13;
	$g_tssEnt.fs = 0x13;
	$g_tssEnt.gs = 0x13;
}
// Initialize the GDT
function gdtInit()
{
	// Setup the pointer
	$g_gdtPtr.limit = (sizeof(GDT_ENTRY)*5)-1;
	$g_gdtPtr.base = (u32)@g_gdtEnt[0];
	// Setup the segments
	gdtSetGate(0, 0x00000000, 0x00000000, 0x00, 0x00);	// Null segment
	gdtSetGate(1, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF);	// Kernel code segment
	gdtSetGate(2, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF);	// Kernel data segment
	gdtSetGate(3, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF);	// User code segment
	gdtSetGate(4, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);	// User data segment
	//gdtSetTss(5, 0x0010, 0x00000000);					// TSS
	// Flush the GDT (and TSS)
	gdtFlush();
	tssFlush();
}
// Modify the kernel stack
function gdtSetKernelStack(u32 esp)
{
	$g_tssEnt.esp0 = $esp;
}
// The actual main entry point for the logic of the program
function kmain(u32 magic, MULTIBOOT_INFO* pMBoot) // function keyword uses __stdcall convention. Use cdeclfunction for C styled functions.
{
	// Unused parameters
	#pragma unused($magic)		// avoid "unused parameter" warnings
	#pragma unused($pMBoot)		// avoid "unused parameter" warnings
	// Initialize
	gdtInit();
	ktmInit();
	// Write something to the screen
	ktmWrite("Hello, World!\n\tThis is a test.");
}
Cheers,
-naota

Re: Language Made Just For Developing Kernels

Posted: Wed Oct 14, 2009 4:02 pm
by NickJohnson
I really don't see how this deviates from C, except for some small syntax differences and the ability to use a db/dw/dd syntax (which does the same thing as a globally declared structure btw). You could just add some (non-portable, but you're using inline asm already) keyword/pragma extensions to C to do everything you've added. Sorry, I'm not convinced.

Re: Language Made Just For Developing Kernels

Posted: Wed Oct 14, 2009 6:14 pm
by neon
Why do you need a new language for a kernel anyways? What is the benifate of it over C - which was originally also written for systems development.

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 12:57 am
by Solar
IIRC the language C was designed to write the Unix kernel in...

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 1:39 am
by AJ
Hi,

I agree with the comments above and as Solar said, C is a system programming language. This may just be personal opinion, but the outline code looks like a complete mishmash.

On a more positive note, if you want the IO and memory builtins, why not instead develop a freestanding cross-platform library? That way, it can be used from my favourite C/C++ compiler. A less lofty goal, but IMO more useful.

Cheers,
Adam

[edit: Just realised what I said with regard to freestanding / cross platform and IO! If you were developing such a library, however, theres no reason why you couldn't make it build correctly for several architectures...]

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 2:13 am
by Solar
On a related note, may I point out the C header <iohw.h>, which has been added with ISO/IEC TR 18037. (Refer to Dinkumware Compleat Libraries Reference for details.) For any "kernel development" language you'd have to implement something like this anyway, and you could just as well do it in a standarized way.

(Footnote: Yes, these extensions will go into PDCLib. Post-v1.0, I am afraid.)

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 5:18 pm
by AaronMiller
Yes, I'm aware C was made for the Unix kernel. I'm just floating out an idea and wondering what people thought of it. :)
I am aware that this holds no real benefits, I just thought it looked "fun" IMO.

Thanks for the fast responses guys. :)

Cheers,
-naota

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 7:00 pm
by earlz
AaronMiller wrote:Yes, I'm aware C was made for the Unix kernel. I'm just floating out an idea and wondering what people thought of it. :)
I am aware that this holds no real benefits, I just thought it looked "fun" IMO.

Thanks for the fast responses guys. :)

Cheers,
-naota
If your going to do this just for fun, at least reach a little further than C. I would recommend trying to implement somethign like functional or meta programming as a systems language.. there's yet to be such a language(common, or modern) that can do this and produce free standing code.

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 7:14 pm
by AaronMiller
earlz, can you give an example of what you mean?

Cheers,
-naota

Re: Language Made Just For Developing Kernels

Posted: Thu Oct 15, 2009 10:18 pm
by earlz
http://en.wikipedia.org/wiki/Category:P ... _paradigms implement a programming language that works by one of those paradigms(not including procedural)

Re: Language Made Just For Developing Kernels

Posted: Fri Oct 16, 2009 3:09 am
by f2
AaronMiller wrote: Anyways, here's the example. "kernel.s" Excuse the tabbing of it.
I also agree. I think it looks too much C. In this case, it would be better to use the C language for your OS.
And a language only designed for writing OS, I do not see too much interest. I try to create my own programming
language (inspired from PL/M), which will be used first to write my OS, and later the compiler itself (and also my
assembler).

Re: Language Made Just For Developing Kernels

Posted: Fri Oct 16, 2009 3:23 am
by Solar
And we haven't talked about the "usual suspects" when it comes to "roll your own language". You need a compiler, supporting the object format that linkers understand. You need that compiler reasonably bug-free. You need a debugger. You need documentation. You need help available via Google search.

Until you have all that, your language won't be useable for people, even if it were better suited to do the job.

The greatest language of the world, described in minute detail on some website, doesn't help me zilch when I want to write software in it. ;-)

Re: Language Made Just For Developing Kernels

Posted: Fri Oct 16, 2009 3:53 pm
by Daevius
Hehe, honestly I've had many new idea's that could improve C at some point, including a few you have there as well. The thing is that I hate documenting...being that one of the most important things to do when you want others using your stuff...also, I can write the ideas on paper, but I sure do have to build a nice compiler. Building it is a lot of work, not undoable, but just loads of work. Flex and Bison are great, but getting your compiler to do clever optimizations, well, you're a master of programming if you can build a program that optimizes others their code.

At the moment, I know making an OS or a compiler is too much work to complete, it's just fun to work at and think about, it broadens your view and expertise. I do work on a big library, which is also very hard work...not to mention the doubts if it's actually useful and actually well written...gosh

To be honest, I don't really like a language which has one job...I rather have a language that can handle everything, but can loads modules (libraries) that ease different subjects of programming.

Re: Language Made Just For Developing Kernels

Posted: Sat Oct 17, 2009 2:17 pm
by AaronMiller
Hmm, I see. Well, there are a lot of things I could do with a language like this. But it seems there's no point in it. It'd probably be better to just port over "TinyC" and use that as a scripting language for an OS, heh heh. (Personally I would prefer to script things in C.)

Cheers,
-naota

Re: Language Made Just For Developing Kernels

Posted: Mon Oct 19, 2009 10:37 am
by earlz
AaronMiller wrote:Hmm, I see. Well, there are a lot of things I could do with a language like this. But it seems there's no point in it. It'd probably be better to just port over "TinyC" and use that as a scripting language for an OS, heh heh. (Personally I would prefer to script things in C.)

Cheers,
-naota
C is missing the magic eval() function though