A Zig-es megoldás nem áprilisi tréfa ;-)
Egyébként nézhetjük úgy is, hogy két vagy három megoldást is adtam Zig-ben.
1. Elf megoldás
2. Exe megoldás
3. noptr megoldás
Az 1. és 2. az ténylegesen egy megoldás fizikailag is, de két formátumra (architektúrára) van lefordítva.
A 3. pedig a noptr-es megoldás, ami kicsit csalás, mert a linkelésnél adjuk meg a pointereket.
Ami érdekesebb, hogy kétféleképpen is megadtam az idt tábla töltését. Az egyik a C-s, bitvadász megoldás:
idt[32 * 2] = @shlExact(@intFromPtr(&isrHandler) & 0xffffffffffff0000, 32) | 0x8E0000200000 | (@intFromPtr(&isrHandler) & 0xffff);
Ez egyetlen sor, de hatalmas hibalehetőségekkel.
A másik terjedelmes, de sokkal biztonságosabb és (szerintem) olvashatóbb megoldás:
const interrupt_descriptor_64_t = packed struct {
base_low: u16,
selector: u16,
ist: u8,
flags: u8,
base_mid: u16,
base_high: u32,
reserved: u32,
};
const idtType = [48]interrupt_descriptor_64_t;
load_idt: *const fn (idt_address: *const idtType, idt_size_in_bytes: u16) callconv(.C) void,
...
const isrh = packed union {
addr: packed struct {
low: u16,
mid: u16,
high: u32,
},
ptr: usize,
}{ .ptr = @intFromPtr(&isrHandler) };
idt[32] = interrupt_descriptor_64_t{
.base_low = isrh.addr.low,
.selector = 32,
.ist = 0,
.flags = 0x8e,
.base_mid = isrh.addr.mid,
.base_high = isrh.addr.high,
.reserved = 0,
};
systab.load_idt(&idt, sizeOfIdt);
Természetesen emiatt is lett 75 soros a megoldás, szemben a noptr-es 38 sorral.
A lefordított binárisban nincs nagyon különbség méretben. ;-)