C++ Bare Bones: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
No edit summary |
added nasm code |
||
Line 1: | Line 1: | ||
⚫ | |||
{{In Progress}} |
|||
⚫ | |||
If you have a [[Tutorial:C kernel|GRUB-booting C kernel]] (please read and follow through that document first!), extending it to C++ isn't difficult. All that is needed are a couple of lines to cater for C++ specifics. |
If you have a [[Tutorial:C kernel|GRUB-booting C kernel]] (please read and follow through that document first!), extending it to C++ isn't difficult. All that is needed are a couple of lines to cater for C++ specifics. |
||
==linker.ld== |
==linker.ld== |
||
Using C++ adds two more sections of interest to your kernel binaries: The constructors and destructors of static objects. You have to modify the |
Using C++ adds two more sections of interest to your kernel binaries: The constructors and destructors of static objects. You have to modify the linker script to include them. |
||
<pre> |
<pre> |
||
Line 23: | Line 22: | ||
===NASM=== |
===NASM=== |
||
<pre> |
|||
{{Stub}} |
|||
extern start_ctors, end_ctors, start_dtors, end_dtors |
|||
_loader: |
|||
mov esp, stack+STACKSIZE ; set up the stack |
|||
push eax ; Multiboot magic number |
|||
push ebx ; Multiboot info structure |
|||
static_ctors_loop: |
|||
mov ebx, start_ctors |
|||
jmp .test |
|||
.body: |
|||
call [ebx] |
|||
add ebx,4 |
|||
.test: |
|||
cmp ebx, end_ctors |
|||
jb .body |
|||
call _main ; call kernel proper |
|||
static_dtors_loop: |
|||
mov ebx, start_dtors |
|||
jmp .test |
|||
.body: |
|||
call [ebx] |
|||
add ebx,4 |
|||
.test: |
|||
cmp ebx, end_dtors |
|||
jb .body |
|||
hlt ; halt machine should kernel return |
|||
</pre> |
|||
===GAS=== |
===GAS=== |
||
Line 72: | Line 102: | ||
;Does anyone know if those .ctors and .dtors are specific to some compiler or if there's an ABI stating them ? |
;Does anyone know if those .ctors and .dtors are specific to some compiler or if there's an ABI stating them ? |
||
:It's defined in the ELF ABI for System V platforms, but it's used by most unices. The concept of using a constructor/destructor list for bootup is not so much specified by any C++ ABI, but it is used in pretty much all implementations (not checked, but probably all). |
:It's defined in the ELF ABI for System V platforms, but it's used by most unices. The concept of using a constructor/destructor list for bootup is not so much specified by any C++ ABI, but it is used in pretty much all implementations (not checked, but probably all). |
||
;Does anyone know how to |
;Does anyone know how to control the order of the static ctor's ? |
||
:It is assumed that the compiler puts them into the correct order. However, it is probably best to keep interdependencies at an absolute minimum. |
:It is assumed that the compiler puts them into the correct order. However, it is probably best to keep interdependencies at an absolute minimum. |
||
Revision as of 09:48, 5 January 2007
- This tutorial sets up only the most basic bootable C++ kernel. For more information on C++ kernels see C++.
If you have a GRUB-booting C kernel (please read and follow through that document first!), extending it to C++ isn't difficult. All that is needed are a couple of lines to cater for C++ specifics.
linker.ld
Using C++ adds two more sections of interest to your kernel binaries: The constructors and destructors of static objects. You have to modify the linker script to include them.
.data ALIGN (0x1000) : { start_ctors = .; *(.ctor*) end_ctors = .; start_dtors = .; *(.dtor*) end_dtors = .; *(.data) }
loader.s
The static constructors have to be called before you enter the main kernel function, and the destructors have to be called after that function returns. This is done by modifying loader.s as follows:
NASM
extern start_ctors, end_ctors, start_dtors, end_dtors _loader: mov esp, stack+STACKSIZE ; set up the stack push eax ; Multiboot magic number push ebx ; Multiboot info structure static_ctors_loop: mov ebx, start_ctors jmp .test .body: call [ebx] add ebx,4 .test: cmp ebx, end_ctors jb .body call _main ; call kernel proper static_dtors_loop: mov ebx, start_dtors jmp .test .body: call [ebx] add ebx,4 .test: cmp ebx, end_dtors jb .body hlt ; halt machine should kernel return
GAS
kernel_loader: mov $(stack + STACKSIZE), %esp # set up the stack push %eax # Multiboot magic number push %ebx # Multiboot data structure # calling static constructors mov $start_ctors, %ebx jmp 2f 1: call *(%ebx) add $4, %ebx 2: cmp $end_ctors, %ebx jb 1b call _main # call kernel proper # calling static destructors mov $start_dtors, %ebx jmp 4f 3: call *(%ebx) add $4, %ebx 4: cmp $end_dtors, %ebx jb 3b hlt # halt machine should kernel return
main.cpp
Now, all that is needed is to declare C style linkage for the kernel entry function, so that its name will not get mangled to C++ linkage style:
extern "C" void _main(multiboot_data* mbd, unsigned int magic); void _main( void* mbd, unsigned int magic ) { // write your kernel here }
Questions
- Does anyone know if those .ctors and .dtors are specific to some compiler or if there's an ABI stating them ?
- It's defined in the ELF ABI for System V platforms, but it's used by most unices. The concept of using a constructor/destructor list for bootup is not so much specified by any C++ ABI, but it is used in pretty much all implementations (not checked, but probably all).
- Does anyone know how to control the order of the static ctor's ?
- It is assumed that the compiler puts them into the correct order. However, it is probably best to keep interdependencies at an absolute minimum.