BareMetal OS - Application Examples

Version 0.5.0 (DRAFT), 14 February 2011 - Return Infinity

This documentation details some application examples in Assembly and C.



Overview

Introduction to writing applications

.

Writing an application in Assembly

All Assembly applications for BareMetal OS must have at least the first two lines below. The BITS option specifies that we want a 64-bit application. The ORG option details the memory address where the application will be running from. Any application started by BareMetal OS will be at the start of the 3rd MiB (Hex 0x200000).

BareMetal OS reserves the first 2 MiB of RAM (Hex 0x0 - 0x1FFFFF) for itself.

The INCLUDE option adds the BareMetal OS function definitions so that you can call the OS's internal functions (like b_print_string).
[BITS 64]				; Compile a 64-bit application
[ORG 0x0000000000200000]		; Memory address where application will be loaded

%INCLUDE "bmdev.asm"			; Include the BareMetal OS function definitions
Here is a complete "Hello world" example written in assembly:
[BITS 64]
[ORG 0x0000000000200000]

%INCLUDE "bmdev.asm"

start:					; Start of program label

	mov rsi, hello_message		; Load RSI with memory address of string
	call b_print_string		; Print the string that RSI points to

ret					; Return to OS

hello_message: db 'Hello, world!', 13, 0
nasm hello.asm -o hello.app

Writing an application in C

Here is a complete "Hello world" example written in C:
#include "libBareMetal.h"

int main(void)
{
	b_print_string("Hello world, from C!\n");
	return 0;
}
We support GCC and Clang for compiling applications in C

GCC

Tested with 4.5.0
gcc -c -m64 -nostdlib -nostartfiles -nodefaultlibs -fomit-frame-pointer -finline-functions -o helloc.o helloc.c
gcc -c -m64 -nostdlib -nostartfiles -nodefaultlibs -fomit-frame-pointer -finline-functions -o libBareMetal.o libBareMetal.c
ld -T app.ld -o helloc.app helloc.o libBareMetal.o

Clang

Tested with 2.7
clang -c -fomit-frame-pointer -o libBareMetal.o libBareMetal.c
clang -c -fomit-frame-pointer -o helloc.o helloc.c
ld -T app.ld -o helloc.app helloc.o libBareMetal.o

Advanced C application

The code below takes advantage of multiple CPU cores if they are available.
#include "libBareMetal.h"

void prime_process();

// primes is set to 1 since we don't calculate for '2' as it is a known prime number
unsigned long maxn=400000, primes=1, local=0, lock=0, process_stage=0, processes=8;
unsigned char tstring[25];

int main()
{
	unsigned long start, finish, k;
	
	process_stage = processes;

	start = b_get_timercounter();		// Grab the starting time

// Spawn the worker processes
	for (k=0; k<processes; k++)
	{
		b_smp_enqueue(&prime_process);
	}

// Attempt to run a process on this CPU Core
	while (b_smp_queuelen() != 0)		// Check the length of the queue. If greater than 0 then try to run a queued job.
	{
		local = b_smp_dequeue();	// Grab a job from the queue. b_smp_dequeue returns the memory address of the code
		if (local != 0)			// If it was set to 0 then the queue was empty
			b_smp_run(local);	// Run the code
	}

// No more jobs in the queue
	b_smp_wait();				// Wait for all CPU cores to finish

	finish = b_get_timercounter();		// Grab the finish time

// Print the results
	b_int_to_string(primes, tstring);	// Print the amount of primes for verification
	b_print_string(tstring);
	b_print_string(" in ");
	finish = (finish - start) / 8;
	b_int_to_string(finish, tstring);
	b_print_string(tstring);
	b_print_string(" seconds\n");

	return 0;
}


// prime_process() only works on odd numbers.
// The only even prime number is 2. All other even numbers can be divided by 2.
// 1 process	1: 3 5 7 ...
// 2 processes	1: 3 7 11 ...	2: 5 9 13 ...
// 3 processes	1: 3 9 15 ...	2: 5 11 17 ...	3: 7 13 19 ...
// 4 processes	1: 3 11 19 ...	2: 5 13 21 ...	3: 7 15 23 ...	4: 9 17 25...
// And so on.

void prime_process()
{
	register unsigned long h, i, j, tprimes=0;

	// Lock process_stage, copy it to local var, subtract 1 from process_stage, unlock it.
	b_smp_lock(lock);
	i = (process_stage * 2) + 1;
	process_stage--;
	b_smp_unlock(lock);

	h = processes * 2;

	// Process
	for(; i<=maxn; i+=h)
	{
		for(j=2; j<=i-1; j++)
		{
			if(i%j==0) break;	// Number is divisble by some other number. So break out
		}
		if(i==j)
		{
			tprimes = tprimes + 1;
		}
	} // Continue loop up to max number

	// Add tprimes to primes.
	b_smp_lock(lock);
	primes = primes + tprimes;
	b_smp_unlock(lock);
}

// EOF


Extra

License

BareMetal OS is open source and released under the 3-clause "New BSD License" (see docs/LICENSE.TXT in the BareMetal OS distribution). Essentially, it means you can do anything you like with the code, including basing your own project on it, providing you retain the license file and give credit to Return Infinity and the BareMetal OS developers for their work.