Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
i think whatever is right: you store your 32-bits offsets (exc*) right into your IDT datas, but under the form of 16 bits words. The problem is that no loader will be able to relocate this properly. Either the linker will complain about this (if you select a relocatable output), or the assembler.
worse possible behaviour is that it compiles and drops the 16 high bits of the address (for instance if you have [ORG 0x10000] in your code, then if exc1 == 0x12345, then the effective IDT address will be 0x00012345 & 0x0000ffff == 0x00002345. I think you now understand why it can easily reboot your PC ...
without any ORG, i guess your CS and DS segment both start at 0x1000:0. in that case, IDT32a should contain idt32+0x10000. If this is not the case, then you'll fall back in the previous problem .
i'm not sure this is the problem, but you should know that some exception push a error code on the stack and that this error code is to be removed by your handler before calling IRETD.
so, i'm not sure it's a good idea to call irq from exc... and especially, its not a good idea to call a real mode handler for a protected mode exception (even for division by zero or debug trap ...)