为什么我不能在保护模式下调用BIOS中断?

14

没错。今天我已经花了三个多小时尝试理解为什么在保护模式下无法调用BIOS ISR。我明白一旦设置了IDT,它不一定会在IVT的常规地址中,加上在保护模式下段没有固定大小等等。但是我仍然不明白为什么你不能创建一个单独的4GB段,将IDT段映射到BIOS IVT,将所有内容设置在ring 0中并进行调用。这样行不行呢?

大多数文章要么说:“记住,在保护模式下不能使用BIOS中断!”而不深入探讨这个问题,要么非常描述性,引用陷阱、异常、图片重映射、缺少权限和段寄存器问题作为其原因。

如果有人能提供一个更加人性化的解释,那将非常有帮助... 我不怀疑文章所说的,我只是想理解为什么这是如此“麻烦”!

先谢谢了!

3个回答

10

我认为最大的问题在于BIOS例程是以假定处理器处于实模式下编写的。如果你从不支持的上下文中调用它们,你不能确定BIOS例程会按预期执行。它们可能会自行失败,或者可能会搞乱处理器状态并将您踢出保护模式。


6
Max,如果操作系统在16位保护模式下运行,你可以创建在ring 0中运行的设备驱动程序,调用一个更简单的BIOS ISR。但在32位模式下,第一个16或32位地址偏移量或立即值将被错误地解释,指令流会失去同步。在实模式或16位保护模式下,默认情况下立即和偏移值为16位,在32位保护模式下为32位,在64位(长)模式下,它们为32位或64位。因此,只能在ISR中使用表示为字节的偏移量(<128,如果我记得正确)和字节立即值。

此外,任何段寄存器加载(除零外)在实模式和任何保护模式下的行为都不同。再次强调,实模式代码和保护模式代码可以共同工作,使编写可工作的代码成为可能,但这并不容易。

例如,

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

将字母“ok”放在实模式文本屏幕的左上角,但要使其在16位或32位保护模式下工作,必须在偏移量0xB800处具有基地址为0x000B8000的全局描述符表项。

但是,如果您只想在16位保护模式下运行,则可以使用更常见的代码:

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

应该同样有效。


3
我回溯了一些旧的东西,所以可能有点偏差,但“受保护”模式的主要目的之一是将敏感/安全代码与应用程序代码隔离开来。原始规范有4个级别,从ring 0到ring 3。实际上,我只看到过操作系统使用ring 0,应用程序使用ring 3。允许应用程序修改或调用中断可能会为它们提供进入操作系统的后门。因此,这样的操作仅对在ring 0运行的代码(即操作系统)可用。使您的代码在ring 0中运行的唯一方法是创建驱动程序。Windows基本上将驱动程序加载到自己的私有内核内存中(尽管在Windows Vista / 7中已经发生/正在发生改变),在ring 0中运行。

1
谢谢Paul。但在这种情况下,是否可以创建一个在ring 0中运行的设备驱动程序,简单地调用适当的BIOS ISR,然后将适当的值返回给应用程序? - Max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接