The OS Development wiki at https://wiki.osdev.org/Bare_Bones contains a sample of writing a very basic "Hello World" x86 kernel using a combination of an assembly file and a C file.
https://github.com/andrewrk/HellOS shows a similar project, but written in a single file using the Zig language.
Is there a way to do the same using C? The options used in Zig seem to have some analogues in gcc, for example this:
const MultiBoot = packed struct {
magic: i32,
flags: i32,
checksum: i32,
};
const ALIGN = 1 << 0;
const MEMINFO = 1 << 1;
const MAGIC = 0x1BADB002;
const FLAGS = ALIGN | MEMINFO;
export var multiboot align(4) linksection(".multiboot") = MultiBoot{
.magic = MAGIC,
.flags = FLAGS,
.checksum = -(MAGIC + FLAGS),
};
Seems to be translatable to:
const int32_t ALIGN = 1 << 0;
const int32_t MEMINFO = 1 << 1;
const int32_t MAGIC = 0x1BADB002;
const int32_t FLAGS = ALIGN | MEMINFO;
const struct {
int32_t magic;
int32_t flags;
int32_t checksum;
} multiboot __attribute__((used, aligned(4), section(".multiboot"))) = {
.magic = MAGIC,
.flags = FLAGS,
.checksum = -(MAGIC + FLAGS)
};
And the Zig equivalent of the assembly code:
export fn _start() callconv(.Naked) noreturn {
@call(.{ .stack = stack_bytes_slice }, kmain, .{});
while (true) {}
}
Seems like it could become
void __attribute__((used, naked, noreturn)) start() {
asm (
"mov stack, %esp\n"
"call kmain"
);
while(1);
}
But I haven't been able to get this to be accepted, even though I'm using the same ld file as the Zig example used.
Is this a viable thing to do or I am barking completely up the wrong tree?
(Note: the output kernel only needs to be bootable by qemu --kernel
, not GRUB or anything.)