( enpassant | 2024. 04. 09., k – 20:49 )

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. ;-)