pub inline fn outb(port: u16, value: u8) void { asm volatile ("outb %[value], %[port]" : : [port] "N{dx}" (port), [value] "{al}" (value), ); } const VGATerminal = struct { const width = 80; const height = 25; const vram: *[width * height]u16 = @ptrFromInt(0xB8000); offset: u16 = 0, foreground: u8 = 0x07, background: u8 = 0x00, pub fn put(self: *VGATerminal, ch: u8) void { const cell = ch | (@as(u16, self.foreground) << 8) | (@as(u16, self.background) << 12); vram[self.offset] = cell; self.offset += 1; } fn checkpos(self: *VGATerminal) void { if (self.offset >= width * height) { const onebefore = (width - 1) * height; @memcpy(vram, vram[width..onebefore]); @memset(vram[onebefore..], 0); self.offset = onebefore; } } pub fn updatecursor(self: VGATerminal) void { outb(0x03d4, 0x0f); _ = self; } }; export fn zigit() void { var vga = VGATerminal{}; vga.foreground = 0x0f; vga.put('H'); vga.put('i'); vga.updatecursor(); }