So I had a look at your interrupt code, because I bet the problem's there. Sure enough, _pushalgen, _pushald, _popalgen, and _popald cannot work. You defined them as functions, but they push or pop values and then return. Return is not a magic instruction that knows where the corresponding call was, it is essentially just "pop EIP". So stack manip will not work this way. The things you have written might work as macros, though.
Also, to help you out with your "idt stub table", where you are apparently trying to list all ISRs in order: Well, I wouldn't do that, exactly. If you insist on handling all ISRs generically, one way would be to actually have the code pointers constant offsets from each other. Let's see here... You can install all gates as interrupt gates (which you should do anyway, and I notice you are already doing) then there is no need for the CLI instruction. So the stub for each ISR is just possibly a push 0, then a push vector and jmp isr. I'd suggest you actually completely fill up the IDT, which will make it easier later on to support APIC and MSI. For now, handle all unknown interrupts by panicking.
So the jmp isr is two bytes if isr is within 128 bytes of the jmp instruction. Since there are going to be 256 entries in our table, each at least one byte large, this isn't going to happen. In protected mode, the only alternative is jmp with a 32-bit offset, which is five bytes. So that comes out to up to nine bytes per entry. Which is awkward to work with, so let's make it sixteen bytes. The you can define something along these lines:
Code:
.p2align 4
.global isr0
isr0:
num=0
.rept 32
.p2align 4
.if ((1 << num) & 0x22ff00)
pushl $0
.endif
pushl $num-128
jmp isr
num=num+1
.endr
.rept 256-32
.p2align 4
pushl $0
pushl $num-128
jmp isr
num=num+1
.endr
Then in C you can define something like
Code:
extern const char isr0[];
And then you know you have one ISR every 16 bytes from there. Easy to loop over.