中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-16 09:35
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 关于程序大于64K后,无法运行的问题 查看 2,065 回复 7
楼 主 关于程序大于64K后,无法运行的问题 发表于 2010-11-09 11:45 ·  中国 广东 深圳 电信
初级用户
积分 65
发帖 26
注册 2010-07-29 17:15
UID 171437
性别 男
状态 离线
我的程序,编译链接后大概在60-70K之间,内存小模式。。。
我发现,在有的DOS上,超过64K就无法运行了,但是有的机器上,又可以运行。。。程序没什么变化。。。
这是为什么啊?
[已使用 Gemini 解答]
Gemini 解答

在 DOS 环境下,程序超过 64KB 后出现运行不稳定的情况,主要与 x86 实模式的段地址架构、可执行文件格式(.COM 与 .EXE)以及内存模型的定义有关。以下是针对该现象的技术解释与修正:

1. 内存模型与段限制

在 16 位 DOS 编程中(如使用 Turbo C, Borland C++, Microsoft C 等),“小模式”(Small Model)的定义是:

  • 代码段(Code Segment):仅限一个,最大 64KB。
  • 数据段(Data Segment):仅限一个,最大 64KB(包含全局数据、堆栈和堆)。

如果程序编译链接后的总大小在 60-70KB 之间,它必须以 .EXE 格式运行。如果该程序被错误地构建为 .COM 格式(Tiny Model),则由于 .COM 文件限制整个程序(代码+数据+堆栈)必须位于同一个 64KB 的段内,超过 64KB 的部分将无法被正确寻址或加载,导致程序崩溃或 DOS 提示 "Program too big to fit in memory"。

2. .EXE 文件的加载机制

当程序为 .EXE 格式时,虽然单个段限制为 64KB,但程序总长度可以超过 64KB。在某些机器上运行正常而在另一些机器上失败,通常由以下因素导致:

  • 常规内存(Conventional Memory)不足: .EXE 文件头中包含 MinAllocMaxAlloc 两个参数,定义了程序运行所需的最小和最大附加内存。如果目标机器加载了过多的 TSR(内存驻留程序)或驱动(如 EMM386.EXEMOUSE.COM、光驱驱动等),导致剩余的连续常规内存小于程序所需空间,程序将无法启动。
  • 堆栈溢出与段边界重叠: 在 Small Model 下,数据段和堆栈段通常共享同一个 64KB 区域。如果程序代码加上数据接近 64KB,且未正确设置 STACK 段的大小,加载器可能会将堆栈指针(SS:SP)初始化在接近段边界的位置,导致运行时压栈操作溢出段界限,触发不可预知的行为。

3. 环境依赖性原因

不同机器表现不一致的工程原因:

  • DOS 版本差异:不同版本的 DOS(如 MS-DOS 6.22, FreeDOS, PC-DOS)其内核占用的常规内存大小不同,直接影响了程序可用的最大内存块。
  • CONFIG.SYS 配置:是否使用了 DOS=HIGH,UMB 将系统组件加载至高内存区(HMA)或上位内存区(UMB),决定了 640KB 常规内存的可用余量。
  • 编译器默认行为:部分编译器在 Small Model 下,如果未显式指定段定义,可能会产生不规范的重定位表,在某些内存寻址边界(如跨越 640KB 物理边界或与特定硬件 I/O 冲突)时失效。

4. 技术修正与建议

  • 确认文件格式:如果程序必须超过 64KB,必须放弃 Tiny Model(.COM),使用 Small 或更大的内存模型(Medium/Large),并确保生成标准 .EXE 格式。
  • 检查 Linker 参数:检查链接器生成的 Map 文件,确认代码段和数据段的实际占用情况。如果代码段接近 64KB,应考虑切换至 Medium Model(多代码段,单数据段);如果数据量大,则应切换至 Compact Model(单代码段,多数据段)。
  • 验证加载环境:使用 MEM /C 命令检查目标机器的常规内存状态。若程序在某些机器无法运行,需确认是否有足够的连续内存(Largest Executable Program Size)来容纳该 70KB 的程序及其堆栈。

在实模式下,超过 64KB 并非物理极限,而是软件架构由“单段”向“多段”过渡的转折点。若程序在某些环境下失效,核心原因在于该环境下的常规内存碎片化或可用空间不足以支撑程序头定义的最小运行内存要求。

2 发表于 2010-11-16 22:18 ·  中国 北京 联通
高级用户
★★
积分 506
发帖 187
注册 2005-12-04 22:41
UID 46500
性别 男
状态 离线
加上himem试试呢
3 发表于 2010-11-18 21:42 ·  中国 广东 深圳 电信
初级用户
积分 65
发帖 26
注册 2010-07-29 17:15
UID 171437
性别 男
状态 离线
都加上了,是不是在某种情况下有限制啊?
4 发表于 2010-11-26 07:49 ·  中国 福建 厦门 电信
高级用户
★★★
积分 741
发帖 366
注册 2007-07-25 19:11
UID 94024
性别 男
状态 离线
编译成Large模式44
5 发表于 2010-11-29 17:34 ·  中国 香港 城市电讯有限公司
银牌会员
★★★
阿林
积分 1,410
发帖 497
注册 2004-06-28 00:00
UID 27551
性别 男
来自 九龍,香港
状态 离线
Originally posted by yysn at 2010-11-9 11:45 AM:
我发现,在有的DOS上,超过64K就无法运行了,但是有的机器上,又可以运行。。。程序没什么变化。。。
这是为什么啊?



相 信 是 HIMEM 和 EMM386 配 置 出 問 題 , 這 裡 有 些 可 取 代 HIMEM 和 EMM386 的 檔 案 和 文 件 , 內 有 範 例 , 雖 然 是 英 文 , 可 試 試 看 :

http://johnson.tmfc.net/dos/driver.html

我 的 網 站 - http://optimizr.dyndns.org
6 发表于 2010-12-03 15:53 ·  中国 广东 电信
初级用户
积分 65
发帖 26
注册 2010-07-29 17:15
UID 171437
性别 男
状态 离线
编译成Large模式44
----------------------------------
编译成L模式之后,程序大了好多啊!
7 发表于 2010-12-03 15:57 ·  中国 浙江 杭州 拱墅区 电信
初级用户
积分 30
发帖 9
注册 2008-04-27 20:00
UID 117121
性别 男
状态 离线
1、楼主能够说明下你是什么程序,用什么编译器吗?
2、small内存模式,由于“段”的原因,因为限制就是2^16=64k,所以。。。
8 发表于 2010-12-13 21:16 ·  中国 广东 电信
初级用户
积分 65
发帖 26
注册 2010-07-29 17:15
UID 171437
性别 男
状态 离线
楼上的,我是编译出来的可执行文件超过了64K
论坛跳转: