【问题标题】:How to know that current mode is real or big real mode?如何知道当前模式是实模式还是大实模式?
【发布时间】:2013-03-11 14:05:49
【问题描述】:

假设我的 API 是从一个只能在实模式或大实模式下工作的系统调用的。我的 API 应该显示当前的系统模式。那它怎么知道当前模式是实模式还是大实模式呢?

注意:

  1. 在大实模式下,CR0 中的保护模式启用位被禁用,因此检查它没有任何区别。
  2. 即使启用了 A20 地址线并不意味着它处于大实模式。

【问题讨论】:

    标签: assembly x86 bios real-mode


    【解决方案1】:

    如果你执行这个:

    mov ebx, 0x10000
    mov al, [ebx]
    

    并得到一个#GP,那么DS 的段描述符的原始限制为0xFFFF,这是普通实地址模式和虚拟8086 模式的情况。

    如果您没有从mov al, [ebx] 获得#GP,则原始限制已超出 0xFFFF(通常为 0xFFFFFFFF,但不一定如此)。

    顺便说一句,在尝试上述操作之前可以并且可能应该检查 v86 模式(以防您的主机操作系统无法正确地向您的处理程序反映异常)。执行smsw获取cr0.pe。它将在 v86 模式下设置为 1,在实地址模式下设置为 0。直接用mov读取cr0会在v86模式下生成#GP,这就是为什么smsw是首选方法。

    【讨论】:

      【解决方案2】:

      在大实模式下,实模式地址别名会失败。假设您处于大实模式,并且您的 DS 的值为 0x6000。由于 DS 的描述符缓存已重新加载(大实模式的定义),因此 DS:0 的物理地址不是 0x60000。如果你用另一个段寄存器命中 0x60000,那将不是同一个内存位置。

      所以这里有一个食谱。在数据段中创建一个临时变量。请注意其 offset 相对于 DS。用 DS-1 的值加载 ES,改变变量的值,看看是否在 ES:(offset+0x10) 处得到相同的值。为防止误报,请重复两次。

      这不会检测到虚拟 86 模式。此外,如果 ES 也通过缓存描述符指向高内存,那么当您重新加载 ES 时,这将丢失。确保调用者代码不会依赖 ES 保持完整。

      大实模式本身不是 CPU 模式 - 没有寄存器位显示“我们现在处于大实模式”。这只是使用香草实模式的 i386 特定逻辑访问高内存的一种方式。上面的过程只检查 DS 是否被这样处理;根据实现的不同,DOS 扩展器可能已经通过 ES 描述符重新加载实现了 big real,同时保留了 DS vanilla。 Wikipedia 说,有时甚至 CS 也会以这种方式别名,尽管由于中断,这是一个棘手的命题。

      【讨论】:

      • BRM 与别名无关。段基地址保持等于segment value * 0x10。但是,段限制设置为大于 0xFFFF 的值,允许偏移量 >= 0x10000。这就是 BRM 的全部意义所在。
      【解决方案3】:

      在 90 年代初期,我们使用一种未记录的方法让我们能够在 REAL 模式(现在可能称为 BIG REAL MODE)下访问 4Gig。方法是进入保护模式,将粒度位更改为 1(表示 4K 粒度而不是 1 字节粒度),然后返回实模式并将所有段寄存器设置为 0。然后您可以使用 ebx 等访问4G 内存。

      因此,如果这就是您所说的,请尝试进入保护模式并检查粒度位的设置。对不起,我所有的旧手册都在阁楼里。如果你需要这些信息,我可以把它们挖出来。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 2011-06-22
        • 1970-01-01
        • 1970-01-01
        • 2010-12-24
        • 1970-01-01
        相关资源
        最近更新 更多