为啥我不能从保护模式调用 BIOS 中断?

Posted

技术标签:

【中文标题】为啥我不能从保护模式调用 BIOS 中断?【英文标题】:Why can't I call BIOS interrupts from protected mode?为什么我不能从保护模式调用 BIOS 中断? 【发布时间】:2011-08-13 07:01:02 【问题描述】:

没错。我今天花了三个多小时试图理解为什么在保护模式下不能调用 bios ISR。我明白了,一旦你设置了 IDT,它就不一定在 IVT 的常用地址中,加上段在保护模式下没有固定大小等。但我仍然不明白你为什么不能创建一个 4GB段,将您的 IDT 段映射到 BIOS IVT,将所有内容设置在环 0 中并调用它们。那不应该工作吗?

大多数文章要么说:“记住你不能在保护模式下使用 BIOS 中断!”没有探索该主题或具有极强的描述性,并引用陷阱、异常、图片重映射、缺乏权利和段寄存器问题作为其背后的原因。

如果有人能提出更人性化的解释,那将非常有帮助......我并不怀疑文章所说的,我只是想了解为什么它会如此“痛苦”!

提前致谢!

【问题讨论】:

【参考方案1】:

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

【讨论】:

非常感谢您的意见!【参考方案2】:

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

此外,任何段寄存器加载(非零)在实模式下的行为与在任何保护模式下的行为不同。同样,实模式代码和保护模式代码可以一起工作,从而可以编写出有效的代码,但这并不容易。

例如,`

  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 个级别,从环 0 到环 3。在实践中,我只见过用于操作系统的环 0 和用于应用程序的环 3。允许应用程序修改或调用中断可能会为它们提供进入操作系统的后门。因此,此类操作仅适用于在环 0 中运行的代码 - 即操作系统。让代码在 ring 0 中运行的唯一方法是创建驱动程序。 Windows 基本上会将驱动程序加载到它自己的私有内核内存中(尽管这在 Windows Vista/7 中已经/正在改变)在环 0 中运行。

【讨论】:

谢谢保罗。但在这种情况下,难道不能创建一个在环 0 中运行的设备驱动程序,它只需调用适当的 BIOS ISR,然后将适当的值返回给应用程序吗?

以上是关于为啥我不能从保护模式调用 BIOS 中断?的主要内容,如果未能解决你的问题,请参考以下文章

切换到保护模式后“呼叫”

操作系统的用户模式、内核模式、实模式、保护模式都是啥?有啥区别和联系?

操作系统修炼指南——保护模式

从王者荣耀看设计模式(保护代理模式)

为啥我不能在同一类的受保护方法中调用方法[重复]

为啥我不能在 PHP 中调用这个受保护的函数?