One way to avoid some of the tricky stuff with booting the system is to boot DOS on the system, load the OS code with a small DOS program, and then start your OS.
That way, you don't have to worry about boot-loading.
Once you have something that can load a binary file, you then have the task of "taking control of the processor".
In x86, that consists of:
Code:
1. Get into 32-bit protected mode,
a) set up a GDT (Global Descriptor Table) with one code-segment (CS) and one data-segment (DS).
b) set CR0.PE (bit 0) to one.
c) jump a far-jump using the index of the CS.
d) set DS, ES, SS, FS, GS to the datasegment.
2. Set up a protected mode vector table (Interrupt Descriptor Table, IDT).
3. Set up the interrupt controller (8259 or APIC) to use vectors 0x20 and up [you may choose other vector numbers, but I don't know of a good reason for that].
4. Configure a timer device (e.g. the 8254 or a High Res Timer). Set the corresponding interrupt up and enable interrupts.
Most of the above CAN be written in C, but you really need to know what you are doing. If not, it's probably easier to do in assembler.
Now you are ready to actually start writing task-switching code, etc.
By the way, another way to get the system started without writing your own boot-loader would be to use GRUB and write your code as "grub modules", which isn't very hard if you have access to GNU tools.
--
Mats