I have a program that is over 1M, and I'm wondering how it runs in DOS. Everyone, please give me some pointers.
Last edited by pkuwc on 2010-1-25 at 17:35 ]
LLM 解释
结论
DOS 下运行超过 640KB 的程序依赖 扩展内存(XMS) 或 扩充内存(EMS) 的内存管理机制,通过保护模式或实模式下的内存分页/映射实现。具体实现需依赖编译器、内存管理器的支持,且受硬件配置和 DOS 版本限制。
技术前提与限制
-
实模式的内存限制
DOS 默认运行在 x86 实模式下,仅能直接访问前 1MB 内存(地址范围 0000:0000 到 FFFF:FFFF,实际物理地址为 0x00000 到 0xFFFFF),其中前 640KB(0x00000 到 0x9FFFF)为常规内存(Conventional Memory),剩余 384KB 为保留内存(用于显存、BIOS、硬件接口等)。因此,实模式下无法直接运行超过 640KB 的程序。
-
扩展内存(XMS)与保护模式
- 若程序超过 1MB,需通过 保护模式 访问扩展内存(XMS,即 1MB 以上的物理内存)。保护模式下 x86 处理器可访问 4GB 物理内存(32 位模式),但需内存管理器(如 HIMEM.SYS)和 DOS 扩展器支持。
- 常见的 DOS 扩展器包括 DOS/4GW(由 Rational Systems 开发,广泛用于 Watcom C++ 编译的程序)、Phar Lap 386 DOS Extender 等。扩展器负责在实模式与保护模式间切换,管理内存分页,并提供 DOS 系统调用的兼容层。
-
扩充内存(EMS)与内存映射
- 若程序使用扩充内存(EMS,即通过内存分页映射到保留内存的扩展内存),则需 EMS 管理器(如 EMM386.EXE)支持。EMS 将 1MB 以上的内存分成 16KB 的页帧,映射到保留内存中的 64KB 窗口(通常位于
0xA0000 到 0xBFFFF),程序通过访问该窗口间接使用扩展内存。但 EMS 主要用于数据存储,而非程序代码加载(代码需连续地址空间),因此超过 1MB 的程序较少依赖 EMS。
当年的常见误解
- 部分用户可能误以为实模式下可通过“特殊指针”访问 1MB 以上内存,这是对实模式地址空间的误解:实模式下
FFFF:FFFF 对应的物理地址为 0xFFFF0 + 0xFFFF = 0x10FFEF,但处理器会将其截断为 20 位(即 0x0FFEF),因此无法访问 1MB 以上内存。
- 另一个误解是将“内存扩充”(EMS)与“内存扩展”(XMS)混淆,前者依赖分页映射,后者依赖保护模式,两者的实现机制与适用场景完全不同。
后续优秀回复补充
cir2633 提到的 DPMI(DOS Protected Mode Interface)是关键背景:DPMI 是 1990 年代定义的保护模式接口标准,允许程序在 DOS 下直接使用保护模式,并通过 DPMI 服务器(如 Windows 3.x 的 WINOLDAP、DOSBox 的内置支持)与实模式 DOS 交互。Watcom C++ 和 DJGPP 正是通过 DPMI 实现保护模式编程,从而支持超过 1MB 的程序运行。