Page 1 of 1

Exception handling

Posted: Wed Oct 01, 2003 3:16 pm
by stonedzealot
I'll be brief (but I'm not tired this time, so I'll be descriptive too). I have a small kernel with a working IDT (e.g. interrupts I call from the kernel fire the ISR and return to where they're supposed to). I don't have problems with exceptions now, but I want to build in exception error code support into the ISRs now, so I don't have to screw with them later (except tweaking and refining, of course).

My understanding of error codes is that they are 32 bit values at the top of the stack when the ISR is accessed, and they are only pushed for interrupts 8 and 10-14. So, if my standard, working, ISR looks like this (with no error handling):

Code: Select all

isr%1:
   pusha      
   push gs      
   push fs
   push ds
   push es
   push dword %1
   call int_master
   add esp, 4   
   pop es      
   pop ds
   pop fs
   pop gs
   popa
   iret      
endisr%1:
(Where int_master is a C function int_master(int interrupt)). However with error code handling, it would look like this:

Code: Select all

isr%1:
   %if %2 = 1
   pop ecx
   %else
   nop
   %endif

   pusha      
   push gs      
   push fs
   push ds
   push es
   push ecx
   push dword %1
   call int_master
   add esp, 8   
   pop es      
   pop ds
   pop fs
   pop gs
   popa
   iret      
endisr%1:
Where int_master is now int_master(int errorcode, int interrupt) and %2 is the second argument of the macro creating the ISRs, which is 1 for and exception w/error code and 0 for any other interrupt/exception. The nop if there is no error code is to keep the lengths of the ISRs the same as the function I use to fill the IDT with the addresses of all the ISRs relies on their uniform length. If there is no error code, the trash ecx value can be accepted as the error code argument of int_master will be ignored.

Is this a correct understanding?

Re:Exception handling

Posted: Wed Oct 01, 2003 3:52 pm
by Pype.Clicker
trashing ecx doesn't sound like a good idea (how will you restore its value ?)

I would rather go for

Code: Select all

;; argument 1 is the exception number, argument 2 is 1 if an error code is present on the stack
%macro EXC 2
isr%1:
   %if %2 = 1
;; assemble nothing
   %else
   push dword 0
   %endif
   pusha      
   push gs      
   push fs
   push ds
   push es
   push esp ;; the C function will receive a pointer to the whole stackframe
   push dword %1;; and the number of the interrupt
   call int_master
   add esp, 8
   pop es      
   pop ds
   pop fs
   pop gs
   popa
   add esp,4 ;; now we drop the error code
   iret   

Re:Exception handling

Posted: Wed Oct 01, 2003 6:53 pm
by stonedzealot
Another related question: A "push dword 0" statement is 5 bytes long, right? I only ask because when I changed the code to:

Code: Select all

isr%1:
   %if %2 = 0
      push dword 0
   %else
      times 5 nop
   %endif
   ...
   add esp, 4
   iret
endisr%1:
The code generates several exceptions (rolled up in the 8th interrupt). Again, the only reason this is an issue is that I have an automated IDT filler-outer that requires the ISRs to be identical in size. But this code:

Code: Select all

isr%1:
   %if %2 = 0
      push dword 0
   %else
      push dword 0
   %endif
   ...
   add esp, 4
   iret
endisr%1:
Works like a charm (only because the second push dword 0 is never reached, no exceptions are firing). The only thing that I can guess is that push dword 0's size != times 5 nop's size and thus everything would get offset exponentially from where it should be after the first exception with an error code.

Any thoughts would be appreciated.

Re:Exception handling

Posted: Thu Oct 02, 2003 1:51 am
by Pype.Clicker
1. maybe "%if %2 == 0" could give better results.
2. "push dword 0" is actually 5 byte longs. (68 00 00 00 00) except if you're in a [bits 16] segment -- where it becomes (66 68 00 00 00 00)

Re:Exception handling

Posted: Thu Oct 02, 2003 5:36 am
by stonedzealot
<sigh>
That's what I thought. Unfortunately (?) I'm in 32 bits and %if %2 == 0 is the same as %if %2 = 0, just as %if %2 != 0 is the same as %if %2 <> 0. The NASM people added these aliases to make C people feel more comfortable.

Oh well, back to debugging the exceptiona :P