14

Right. I've spent over three hours today trying to understand why you can't call a bios ISR when in protected mode. I get that once you set and IDT it wont necessarily be in the usual address for the IVT plus segments dont have a fixed size in Protected mode, etc.. But I still don't get why can't you jsut create a single 4GB segment, map your IDT segments to the BIOS IVT, set everything in ring 0 and call them. Shouldn't that work?

Most articles either say: "Remember you cant use BIOS interrupts in protected mode!" without exploring the subject or are extremely descriptive and cite traps, exceptions, pics remmaping, lack of rights and problems with segment registers as the reason behind it.

It would be extremely helpful if someone could come up with a more human-friendly explanation... I'm not doubting what the articles say, I just want to understand why it is such a 'pain'!

Thanks in advance!

3 Answers 3

10

I think the biggest problem is that the BIOS routines were written assuming the processor is in real mode. If you call them from an unsupported context, you can't be sure the BIOS routines will behave as expected. They could fail on their own, or they could mess up the processor state and kick you out of protected mode.

0
6

Max, you could possibly create the device driver running in ring 0 that calls a simpler BIOS ISR, if the OS is running in 16-bit protected mode. But in 32-bit mode, the first 16- or 32-bit address offset or immediate value would be interpreted incorrectly and the instruction stream would get out of sync. In real or 16-bit protected mode, the immediate and offset values are by default 16 bits long, in 32-bit protected mode they are 32 bits long, and in 64-bit (long) mode, they are either 32 or 64 bits long. So only offsets represented as bytes (< 128, if I remember correctly) and byte immediate values can be used in the ISR.

Further, any segment register load (other than zero) will behave differently in real mode than it does in any protected mode. Again, the real mode code and the protected mode code can work together to make it possible to write code that works, but it is not at all easy.

For example,`

  mov ah, 0B8h  
  mov al, 000h  
  mov es, ax  
  mov byte ptr es:0, 'o'  
  mov byte ptr es:2, 'k'`

will put the letters 'ok' in the upper left corner of a text mode screen in real mode, but to have that work in 16-bit or 32-bit protected mode, a global descriptor table entry at offset 0xB800 has to have a base address of 0x000B8000.

But if you are satisfied with running only in 16-bit protected mode the more common code:`

  mov ax, 0B800h   
  mov es, ax  
  mov dword ptr es:0, 0076b076fh`  

should work just as well.

3

I'm reaching back to old stuff so this might be slightly off, but one of the primary purposes of 'protected' mode is to isolate sensitive/secure code from application code. The original spec had 4 levels ring 0 through ring 3. In practice I've only ever seen ring 0 for the operating system and ring 3 for applications. Allowing applications to modify or invoke interrupts could potentially offer them a back door into the operating system. So such operations are available only to code running in ring 0 - namely the operating system. The only way to get your code to run in ring 0 is to create a driver. Windows will basically load drivers into it's own private kernel memory (though this has/is changing in Windows Vista/7) running in ring 0.

1
  • 1
    Thanks Paul. But in this case shouldn't it be possible to create a device driver running in ring 0 that simply calls the appropriate BIOS ISR and then returns the appropriate values to the application?
    – Max
    Commented Apr 26, 2011 at 19:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.