Memory Map (x86)

来自osdev
跳到导航 跳到搜索

本文描述BIOS跳转到自制bootloader代码时计算机物理内存的内容。(译者注:Bootloader可以翻译为引导加载程序,但是这样翻译很容易把前面的“引导”当作单个动词理解,引起误解,所以本文不再翻译了)

实模式地址空间 (< 1 MiB)

当一台典型的x86 PC启动时,它将处于实模式,带有一个活动的BIOS。 在CPU保持在实模式期间,IRQ0(时钟)将重复触发,用于引导PC的硬件(软盘、硬盘、CD、网卡、USB)也将生成IRQ。 这意味着在PC引导过程中,必须仔细保留实模式IVT (中断向量表,见下文),因为它正在使用中。

IVTIRQ激活时,它将调用BIOS例程来处理IRQ。 Bootloader还将访问BIOS功能。 这意味着BIOS使用的两个内存工作区 (BDA和EBDA) 在引导过程中也必须小心保存。 此外,每次BIOS处理IRQ0(每秒18次),BDA中的几个字节都会被BIOS覆盖 --因此,当IRQ在实模式下处于活动状态时,请勿尝试在那里存储任何内容。

在需要的BIOS功能被调用之后,并且你的内核已被加载到某个地方的内存中时,bootloader或内核可能会永远退出实模式 (通常是进入32位 保护模式)。 如果内核不再使用实模式,那么PC中的第一个0x500字节内存可能会被重用和覆盖。 (但是,为了更改视频显示模式,临时返回实模式是非常常见的。)

当CPU处于保护模式时,系统管理模式 (SMM) 仍然处于无形状态,并且无法关闭。 SMM似乎也在使用EBDA。 因此,EBDA存储区永远不应被覆盖。

注意: EBDA是一个可变大小的内存区域 (在不同的BIOS上)。 如果它存在,它在内存中总是低于0xA0000。 它的大小绝对保证不超过128 KiB。 较旧的计算机通常使用0x9fc00-0x9ffff中的1 KiB,现代固件能使用的更多一些。 你可以通过使用BIOS功能INT 12h或通过检查BDA中0x413处的word来确定EBDA的大小(见下文)。 这两种方法都会告诉你在EBDA之前有多少常规内存可用。

还应注意,你的bootloader代码会被加载并在物理地址0x7C00到0x7DFF的内存中运行。 因此,在执行转移到第二阶段Bootloader或内核之前,那块内存区域可能也无法使用。

概述

开始 结束 大小 描述 type
实模式地址空间(第一个MiB)
0x00000000 0x000003FF 1 KiB 实模IVT (中断向量表) 在实模式下无法使用 640 KiB内存(“下层内存-Low memory”)
0x00000400 0x000004FF 256 bytes BDA (BIOS数据区-BIOS data area)
0x00000500 0x00007BFF 差不多30KiB 常规内存 可用内存
0x00007C00 0x00007DFF 512 bytes 你的OS引导扇区
0x00007E00 0x0007FFFF 480.5 KiB 常规内存
0x00080000 0x0009FFFF 128 KiB EBDA (扩展BIOS数据区-Extended BIOS Data Area) 部分由EBDA使用
0x000A0000 0x000BFFFF 128 KiB 视频显示内存 硬件映射 384 KiB系统/预留(“上层内存-Upper Memory”)
0x000C0000 0x000C7FFF 32 KiB (typically) Video BIOS ROM和硬件映射/Shadow RAM
0x000C8000 0x000EFFFF 160 KiB (typically) BIOS扩展(BIOS Expansions)
0x000F0000 0x000FFFFF 64 KiB 主板BIOS

BIOS数据区(BDA)

BDA只有部分被标准化,主要与实模式BIOS操作相关。 以下是部分列表。 有关更多详细信息,请参阅下面的外部链接参考。

地址(大小) 描述
0x0400 (4 words) COM1-COM4串行的IO端口(每个地址为1个字,如果没有则为零)
0x0408 (3 words) LPT1-LPT3并行IO口(每个地址为1个字,无地址为零)
0x040E (word) EBDA基地址>>4(通常!)
0x0410 (word) 检测到的硬件的打包位标志
0x0413 (word) EBDA/不可用内存之前的千字节数
0x0417 (word) 键盘状态标志
0x041E (32 bytes) 键盘缓冲区
0x0449 (byte) 显示模式
0x044A (word) 文本模式列数
0x0463 (2 bytes, taken as a word) 视频基本输入输出端口
0x046C (word) 自启动以来的IRQ0定时器tick次数
0x0475 (byte) 检测到的硬盘数量
0x0480 (word) 键盘缓冲区开始
0x0482 (word) 键盘缓冲端
0x0497 (byte) 最近键盘LED/Shift键状态

扩展BIOS数据区 (EBDA)

如果你在网上搜索,你可能会看到EBDA的“映射”。 但是,这些映射是针对原始IBM BIOS EBDA的。 当前的BIOS可能使用不同的映射。 EBDA区域没有标准化。

扩展内存(>1 MiB)

1 MiB以上的RAM区域不是标准化的、定义明确的或连续的。 其中可能有包含内存映射硬件的区域,只有设备驱动程序才能访问这些区域。 其中可能有包含你的初始化代码可能希望读取的ACPI表区域,然后可以覆盖和重用这些表。 有些ACPI区域则不能这样 “回收”。 计算机的一些RAM可能会扩展于4 GiB以上。

使用BIOS函数INT 15h, EAX=0xE820获得可靠的扩展内存映射。


开始 结束 大小 区域/异常 描述
High Memory
0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- 自由使用 (如果存在) 扩展内存1,2
0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) 可能的内存映射硬件 ISA Memory Hole 15-16mb 3
0x01000000 ???????? ???????? (不管是否存在) RAM —— 自由使用 更多扩展内存1
0xC0000000 (有时,取决于主板和设备) 0xFFFFFFFF 0x40000000 (1 GiB) 不定(通常为内存映射设备保留) 内存映射PCI设备、PnP NVRAM?、IO APIC/s、本地APIC/s、BIOS.
0x0000000100000000 (4 GiB以上的可能内存) ???????????????? ???????? (不管是否存在) RAM —— 自由使用(PAE/64位) 更多扩展内存1
???????????????? ???????????????? ???????????????? 可能的内存映射硬件 可用于现代硬件中的内存映射PCI设备(但由于向后兼容性,通常不可用)

1: 不同的计算机具有不同的内存容量,因此你可能会发现扩展内存的大小有所不同,可能是“无”(例如,旧的80386系统)到“很多”。

2: 自由使用,除了你的Bootloader (即GRUB) 可能已经在这里加载了你的 “模块”,并且你不想覆盖这些模块。

3: “ISA Memory Hole”(从0x00F00000到0x00FFFFFF)用于内存映射ISA设备(例如视频卡)。 现代计算机不需要这个孔,但一些芯片组仍然支持它(作为可选功能),一些主板可能仍然允许使用BIOS选项来启用它,因此它可能存在于没有ISA设备的现代计算机中。


另见

外部链接