2. The tools
This is the third post in a series, the first one is here.
Let's try and figure out what happened. The only C source file compiled by make was start.c:
gcc -c -I"../../sartoris/include" -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -s start.c -o start.o
Some of the parameters shown above are standard, you probably know them if you have used gcc before. First, -c is telling gcc to just build an object file, that is a machine code version of our program, but not one that is ready to run (because then it would build a program to run on Linux, or whatever your operating system may be, and that is not what we want!). Similarly, the -I and -O2 switches just set the directory for our include files (we need the microkernel definitons) and the optimization level. The following four parameters, however, are relevant to us. They tell gcc to build a program that is independent of the operating system we are currently running - no default libraries, no includes, no nothing. Just our little program, and nothing else, and that is fine. Let's take a look at the source for start.c:
#include "screen.h"
#include <sartoris/syscall.h>
char buffer[256];
int main() {
clear_screen();
cursor_off();
string_print("hola, mundo!", 0, 0x7);
while(1);
}
As you can probably guess, most of the magic in start.c comes from the files screen.h and screen.s. This program is going to run on a freshly booted computer (running in protected mode, and with no access to the BIOS) so the only way to actually show some text is by directly manipulating your graphics card, and that is exactly what screen.s does. Nicolás de Galarreta wrote this little driver to report errors during early stages of Sartoris boot, and we may borrow it now for this experiment. If we were to run this program within, say, the Linux console, it would be natural to end it with something like
return 0;
But since we are on our own, leaving the main function like that doesn't make much sense: there is nowhere to go back to, this is actually the first (and only) program running on the computer. A much wiser choice is to just do nothing until the user, hopefully after enjoying an Spanish "Hello, world!" message, reboots. In case you were wondering, the second parameter to string_print is the position in the screen, while the third is the font color (0x7 is usually solid white, at least in the southern hemisphere).
Of course, some things are happening automagically here. The linker parameters provide more clues on what is going on:
ld --oformat binary --entry 0x00000000 --Ttext 0x00000000 -N --Map start.map -o bin/code.img start.o screen.o
The linker is producing a raw binary from our two object files start.o and screen.o (see the --oformat binary at the start of the command line), assuming the starting address is 0x00000000 (a very long way to spell zero) and saving the result as bin/code.img. Normally, the linker outputs a file following an executable file format (like ELF on Linux or PE under Windows), but here we are asking for a plain binary, i.e. the machine code image of the program exactly as it should be laid out on the machine's memory. This forces the linker to bind each static variable and function to a memory address (since there is no metadata in the file that could help the operating system loader figure out how to compute these addresses later). This binary image is then appended to the microkernel's, with the following commands:
cp ../some/long/route/sartoris.img bin/boot.img
cat bin/code.img >> bin/boot.img
And we are basically set! The first 512 bytes of sartoris.img contain a boot sector that will load the microkernel itself and our binary image. The microkernel will use the first megabyte of memory (both for its code, data structures and video memory). Our image will be loaded at offset 0x800000 (at the eighth megabyte). The microkernel will create an address space, and a thread that will start at this very address (where our main function will be located).
Go to next section.
0 Comments:
Post a Comment
<< Home