Memory Map (x86)
本文描述BIOS跳转到自制bootloader代码时计算机物理内存的内容。(译者注:Bootloader可以翻译为引导加载程序,但是这样翻译很容易把前面的“引导”当作单个动词理解,引起误解,所以本文不再翻译了)
实模式地址空间 (< 1 MiB)
当一台典型的x86 PC启动时,它将处于实模式,带有一个活动的BIOS。 在CPU保持在实模式期间,IRQ0(时钟)将重复触发,用于引导PC的硬件(软盘、硬盘、CD、网卡、USB)也将生成IRQ。 这意味着在PC引导过程中,必须仔细保留实模式IVT (中断向量表,见下文),因为它正在使用中。
当IVT被IRQ激活时,它将调用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设备的现代计算机中。