在 16 位模式下启动时获取 x86 CPU 支持的 "bitness"

Get the supported "bitness" of an x86 CPU when booted in 16-bit mode

我正在开发一个 x86 引导加载程序并且遇到了这个问题(我想这应该很简单,但到目前为止我还没有能够解决):我想检测 CPU 主机(例如,如果它仅支持 16 位,或支持 32 位或 64 位)。

我使用了 CPUID 指令,但它是在 486 中引入的,因此对于检测仅 16 位与支持 32- 的 386 兼容 CPU 没有帮助位保护模式(或带前缀的实模式中的 32 位操作数大小)。

检查 32 位(参见 http://www.rcollins.org/ddj/Sep96/Sep96.html):

  • 16 位 CPUs 无保护模式 (8088/8086/80186) 在执行 pushf[= 时将始终设置标志寄存器的高 4 位 (15-12) 32=]
  • 80286 将始终在 pushf 上清除高 4 位(当 运行 处于实模式时)
  • CPUs 支持 32 位允许在实模式下使用 popf 修改高 4 位(但是所有 4 位应具有相同的值 - 全部设置或全部清除)

通过使用 pushfpopf 并修改堆栈中的数据,您检查是否可以修改高 4 位;如果是,则必须是 32 位 CPU.

正在检查 CPUID

  • 确保 CPU 支持 32 位(见上文)
  • 切换到 32 位模式
  • 检查 EFLAGS 的第 21 位是否可以修改(设置和清除);如果该位的值不固定(可以从 0 更改为 1,反之亦然),则支持 cpuid 指令。