views:

657

answers:

2

I have loaded an idt table with 256 entries, all pointing to similar handlers:

  • for exceptions 8 and 10-14, push the exception number (these exceptions push an error code automatically)
  • for the others, push a "dummy" error code and the exception number;
  • then jump to a common handler

So when the common handler enters, the stack is properly aligned and contains the exception/interrupt number, error code (which may just be a dummy), eflags, cs and eip.

My question regards returning from the interrupt handler. I use iret to return after taking out the exception number and the error code from the stack, but this doesn't work for exception nr 8; if I leave the error code on the stack, then it returns fine!

Questions:

  • do I have to leave the error code on the stack for exceptions that put the error code there? If so, how does iret determine whether it has to pop an error code or not?
  • as soon as I enable interrupts I always get exception 8 (double fault), but then everything runs fine (I'm developing a hobby OS). Is this normal behavior or do I have a bug somewhere?
+7  A: 

If the CPU pushed an error code automatically, the handler must pop it before the iret. The iret instruction doesn't know where you're coming from, if it's a fault, a trap or an external interrupt. It always does the same, and it assumes that there's no error code on the stack.

Quoting from the SDM (Software Developer's Manual), Volume 3, Chapter 5, section 5.13 titled Error Code:

The error code is pushed on the stack as a doubleword or word (depending on the default interrupt, trap, or task gate size). To keep the stack aligned for doubleword pushes, the upper half of the error code is reserved. Note that the error code is not popped when the IRET instruction is executed to return from an exception handler, so the handler must remove the error code before executing a return.

You can find the IA-32 Software Developer's Manual here: http://www.intel.com/products/processor/manuals/

Volume 3 part 1, chapter 5, describes exception and interrupt handling. Volume 2 part 1 has the spec for the iret instruction.

Nathan Fellman
I somehow missed that paragraph :) So now I know this is a bug in my code. Thanks a lot for pointing it out!
João da Silva
+1  A: 

Hi João

I wrote a small x86 OS a while back. Take a look at the file isr.asm in the cvs repository.

Notice how we set up the handlers, most push a dummy dword onto the stack to account for the few handlers that automatically get an error code pushed. Then when we return via an iret we can always assume 2 dwords on the stack irrespective of the interrupt and perform an add esp, 8 before the iret to clean things up nicely.

That should answer your first question.

As for your second question: A double fault when you enable interrupts, ...hmmm could be a problem with paging if you haven't set it up correctly. Could be a million other thing too :)

QAZ
Hi Steve, thanks for the reply :) I don't have paging enabled and I only have 3 valid entries in the GDT (for code and data in ring 0, and another to use in real-mode). I'm usually in protected-mode but I go back to real-mode to use some BIOS routines (mostly reading from the disk). Any clues? :)
João da Silva
Sorry can't think of anything off hand, maybe switching back to real mode causes problems
QAZ