I am sticking to Pmode so don't go saying use VM86.
When switching to pmode from rmode, you lose the use of the INTS. But aren't the INTS inscribed as asm code somewhere in the BIOS? By asm code, I mean opcodes BTW.
Interrupts
Re:Interrupts
If you mean BIOS interrupt services.. yeah, you can get the entry points from the realmode IVT, and the BIOS ROM is at 0x000f0000 - 0x000fffff, so yeah, you could get that and disassemble..
Just remember that it is different with each motherboard model, so you have to deal with it at runtime. Might be just easier to implement vm86 after all..
Just remember that it is different with each motherboard model, so you have to deal with it at runtime. Might be just easier to implement vm86 after all..
Re:Interrupts
The BIOS interrupt handler code is still in memory as machine code, sure, but it's machine code that targets 16-bit real mode. So to run this you need to emulate a 16-bit real mode environment: either using V86 mode, or by switching back to 'real' real mode.
Re:Interrupts
Keep in mind, the issue of using interrupts in general is separate from the issue of using the specific real mode interrupt handlers. I can only presume that you are familiar with these issues alredy, but a review of them might be helpful:
Interrupts are a hardware function that halts the existing sequence of execution, saves the current location to the stack, looks up the interrupt vector in a system table (the IVT in real mode, or the IDT in p-mode), calls the handler, and returns to the halted execution. The primary purpose of interrupts is to allow the system to handle asynchronous signals from the peripherals without requiring them to be polled periodically. The [tt]INT n[/tt] instruction was primarily intended for use in debugging hardware interrupt handlers; its use as a means of vectoring system calls, while planned for from the start, was a secondary use of the existing mechanism, a way of killing two birds with one stone. It is used for system calls, especially in real mode, because a) an interrupt can be called from any code anywhere in the system without regard to the segment base and offset of the calling code; b) because the vectors are set at run time, which means that the actual code can be in different places for different versions of the system software, and c) because it is smaller and faster than an ordinary CALL FAR is.
It is entirely possible to set up your own interrupts in 32-bit protected mode; indeed, you must create at least one a working IDT and the appropriate interrupt handlers for trapping hardware interrupts and CPU exceptions. Furthermore, as Tim pointed out, so long as you don't overwrite the IVT and the BIOS Data Area, the BIOS interrupt handlers and their data will still be in memory and accessible; it is concievable that you could take the vector information from the IVT and use it in creating your IDT. The problem is that the BIOS routines (with a very few exceptions, such as certain special APM and VESA BIOS interrupt handlers which some systems support) are all 16-bit real mode code, and cannot run in 32-bit p-mode; trying to use them in p-mode will crash the whole system.
Any interrupt routines used in p-mode will have to either be written by you from the ground up (though you could easily borrow and modify code from other OSes, where liscensing permits), or else switch to real mode (or Virtual 8086 mode, which if done right allows you to run real-mode software without compromising the OS stability) before running the 16-bit handlers. The former is far and away the better choice, as it allows you greater flexibility in your OS, and avoids many of the problems inherent in the BIOS code; furthermore, the trouble of writing a v86 mode handler (or a system for switching back and forth between real and protected mode) is probably greater than the trouble of writing and debugging your own interrupt handlers is.
However, some hardware functions present special problems with this, specfically determining memory size (which is dependent on the design of the memory local bus of the mother board), Automatic Power Management (motherboard dependent, if present at all), hardware random number generation (ditto), and high-performance graphics (dependent on the video adapter's GPU and chipset). It is not by accident that these are precisely the areas where some BIOS have implemented 32-bit routines, but since only the newest systems support the p-mode BIOS calls, it is necessary on most older systems to use real mode or v86 mode to use those features at all.
Needless to say, the MS-DOS system calls (the [tt]INT 21h[/tt] functions) and the standard device driver interrupts (e.g., the [tt]INT 33h[/tt] mouse services) will not exist in your operating system, unless you implement some kind of emulation of them yourself.
Note also that, while the soft interrupt mechanism is still usable in protected mode, and it is possible to use it for system calls (see the Linux [tt]INT 80[/tt] subsystem as an example), it is inadvisable to use them as the main system interface. Most p-mode systems use call gates or task gates instead, AFAICT, as they are both more flexible and more secure.
I hope that this has clarified the issue somewhat. Comments and corrections welcome.
Interrupts are a hardware function that halts the existing sequence of execution, saves the current location to the stack, looks up the interrupt vector in a system table (the IVT in real mode, or the IDT in p-mode), calls the handler, and returns to the halted execution. The primary purpose of interrupts is to allow the system to handle asynchronous signals from the peripherals without requiring them to be polled periodically. The [tt]INT n[/tt] instruction was primarily intended for use in debugging hardware interrupt handlers; its use as a means of vectoring system calls, while planned for from the start, was a secondary use of the existing mechanism, a way of killing two birds with one stone. It is used for system calls, especially in real mode, because a) an interrupt can be called from any code anywhere in the system without regard to the segment base and offset of the calling code; b) because the vectors are set at run time, which means that the actual code can be in different places for different versions of the system software, and c) because it is smaller and faster than an ordinary CALL FAR is.
It is entirely possible to set up your own interrupts in 32-bit protected mode; indeed, you must create at least one a working IDT and the appropriate interrupt handlers for trapping hardware interrupts and CPU exceptions. Furthermore, as Tim pointed out, so long as you don't overwrite the IVT and the BIOS Data Area, the BIOS interrupt handlers and their data will still be in memory and accessible; it is concievable that you could take the vector information from the IVT and use it in creating your IDT. The problem is that the BIOS routines (with a very few exceptions, such as certain special APM and VESA BIOS interrupt handlers which some systems support) are all 16-bit real mode code, and cannot run in 32-bit p-mode; trying to use them in p-mode will crash the whole system.
Any interrupt routines used in p-mode will have to either be written by you from the ground up (though you could easily borrow and modify code from other OSes, where liscensing permits), or else switch to real mode (or Virtual 8086 mode, which if done right allows you to run real-mode software without compromising the OS stability) before running the 16-bit handlers. The former is far and away the better choice, as it allows you greater flexibility in your OS, and avoids many of the problems inherent in the BIOS code; furthermore, the trouble of writing a v86 mode handler (or a system for switching back and forth between real and protected mode) is probably greater than the trouble of writing and debugging your own interrupt handlers is.
However, some hardware functions present special problems with this, specfically determining memory size (which is dependent on the design of the memory local bus of the mother board), Automatic Power Management (motherboard dependent, if present at all), hardware random number generation (ditto), and high-performance graphics (dependent on the video adapter's GPU and chipset). It is not by accident that these are precisely the areas where some BIOS have implemented 32-bit routines, but since only the newest systems support the p-mode BIOS calls, it is necessary on most older systems to use real mode or v86 mode to use those features at all.
Needless to say, the MS-DOS system calls (the [tt]INT 21h[/tt] functions) and the standard device driver interrupts (e.g., the [tt]INT 33h[/tt] mouse services) will not exist in your operating system, unless you implement some kind of emulation of them yourself.
Note also that, while the soft interrupt mechanism is still usable in protected mode, and it is possible to use it for system calls (see the Linux [tt]INT 80[/tt] subsystem as an example), it is inadvisable to use them as the main system interface. Most p-mode systems use call gates or task gates instead, AFAICT, as they are both more flexible and more secure.
I hope that this has clarified the issue somewhat. Comments and corrections welcome.
Re:Interrupts
Hello Pro from Dover, thanks very much for this useful post on interrupts. I was going to ask at some stage whether (in the opinion of more experienced OS devers than myself of course) it was better to implement task or call gates rather than use the old interrupt model.
Just a quick question, about writing one's own Linux-style INT 80h syscall subsystem, aside from the details of the IDTs, is it just a matter of putting the address of your handler routine in there, a virtual address if using paging, a logical address if segmentation or a physical address if not using any hardware memory management support? Then this means it's just a matter of (let's say in ASM) doing something like this:
mov eax, offset handler_label
mov idt_descr, eax
... discounting that there's some bit fiddling to do in getting the handler routine address in the descriptor for installing in the IDT?
Just a quick question, about writing one's own Linux-style INT 80h syscall subsystem, aside from the details of the IDTs, is it just a matter of putting the address of your handler routine in there, a virtual address if using paging, a logical address if segmentation or a physical address if not using any hardware memory management support? Then this means it's just a matter of (let's say in ASM) doing something like this:
mov eax, offset handler_label
mov idt_descr, eax
... discounting that there's some bit fiddling to do in getting the handler routine address in the descriptor for installing in the IDT?