diff options
Diffstat (limited to 'x86-bare-metal/mbr-pure-zig/mbr.zig')
-rw-r--r-- | x86-bare-metal/mbr-pure-zig/mbr.zig | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/x86-bare-metal/mbr-pure-zig/mbr.zig b/x86-bare-metal/mbr-pure-zig/mbr.zig new file mode 100644 index 0000000..666aa6b --- /dev/null +++ b/x86-bare-metal/mbr-pure-zig/mbr.zig @@ -0,0 +1,106 @@ +const bios = @import("bios.zig"); + +// -- ENTRY POINT --------------------------------------------------------------- + +export fn _entry() linksection(".boot") callconv(.naked) noreturn { + asm volatile ( + // Disable interrupts. + \\cli + // Clear segment selectors. + \\xor %%ax, %%ax + \\mov %%ax, %%ds + \\mov %%ax, %%es + \\mov %%ax, %%ss + \\mov %%ax, %%fs + \\mov %%ax, %%gs + \\mov $0x7c00, %sp + // Long jump to set cs to 0x0000, as some BIOSes load the MBR + // to either 07c0:0000 or 0000:7c000. + \\ljmp $0x0, $main + ); +} + +// -- MAIN ---------------------------------------------------------------------- + +// main should be "callconv(.naked)", once issue is fixed. +// https://github.com/ziglang/zig/issues/18183 +export fn main() noreturn { + for (0..255) |i| { + if (i < bios.ROWS) { + bios.set_pos(@truncate(i)); + } else { + // Once we reach the bottom of the screen start scrolling. + bios.scroll_up(); + bios.set_pos(bios.ROWS - 1); + } + puts_dec(i + 1); + bios.putc(' '); + puts_hex(i + 1); + bios.putc(' '); + bios.putc(@truncate('a' + (i % 26))); + bios.putc(@truncate('a' + (i % 26))); + waste_time(); + } + puts("\ndone"); + + while (true) { + asm volatile ("hlt"); + } +} + +// -- UTILS --------------------------------------------------------------------- + +fn puts(str: []const u8) void { + for (str) |c| { + bios.putc(c); + } +} + +fn puts_dec(init_val: u32) void { + var val = init_val; + var buf: [32]u8 = undefined; + var idx = buf.len; + + while (val > 0 and idx != 0) : (val /= 10) { + idx -= 1; + buf[idx] = @as(u8, @truncate(val % 10)) + '0'; + } + puts(buf[idx..]); +} + +fn puts_hex(init_val: u32) void { + var val = init_val; + var buf: [32]u8 = undefined; + var idx = buf.len; + + while (val > 0 and idx != 0) : (val /= 16) { + idx -= 1; + const digit = switch (@as(u8, @truncate(val % 16))) { + 0...9 => |d| '0' + d, + 10...15 => |d| 'a' + d - 10, + else => '?', + }; + buf[idx] = digit; + } + puts(buf[idx..]); +} + +fn rdtsc() u32 { + return asm volatile ("rdtsc" + : [eax] "={eax}" (-> u32), + : + : "edx" + ); +} + +fn waste_time() void { + const start = rdtsc(); + var now = start; + var idx: usize = 0; + while (now - start < (1 << 28)) : (idx += 1) { + if (idx == 10_000) { + now = rdtsc(); + idx = 0; + } + } +} |