1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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;
}
}
}
|