Normally, ELF constructors are run by the ELF loader (if you are using ELF, that is). However, in case of a kernel, that doesn't happen. The bootloader usually dumps your binary into memory, and then maybe clears BSS, and then that's your lot, then it jumps to your start symbol. If you do require constructors to run, you have to call them yourself. I'm going to continue guessing you use ELF, as I have no idea how exactly this works for PE. You can run all constructors just by running this code:
Code:
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
static void dummy(void) {}
extern void _init(void) __attribute((weak, alias("dummy")));
void run_constructors(void) {
for (void (**it)(void) = __init_array_start; (uintptr_t)it < (uintptr_t)__init_array_end; it++)
(*it)();
_init();
}
Since I literally just came up with this code, you might want to check it for bugs. All these symbols should be declared by the linker. If you ever switch to a higher-half memory model, you can only run this code after the switching on paging. As for the constructors themselves, those are emitted by the compiler.