33字节DOS EXE文件,最短了?
DOS下简单的.EXE文件通常是由汇编、链接工具生成的,但它们一般在文件头内包含了
一个480字节的空白部分,要去掉它们也很容易,只要将02H、04H及08H处的值改变就可以了。
执行代码为mov ah,4ch和int 21h的.exe文件一般是32+480+4字节长,头部如下:
000000 4D 5A 04 00 02 00 00 00 20 00 01 00 FF FF 01 00
000010 00 00 EB 36 00 00 00 00 1E 00 00 00 01 00 00 00
尾部如:
000200 B4 4C CD 21
头尾之间是480字节的NUL字符。02h处改为24,04h处改为01,08h处改为02,原200h处的执行代码移到20h处。
这样,文件长32+4字节。所以,如果这就是EXE文件的常规,那么exe文件的长度,就取决于
执行代码的长度,因为头的长度是固定的32字节。作为正常的文件结束,应该最短了(int 20h只有2字节);再想短
的话,就要使用特别代码如int 19h(重新启动)了。***还有更短的,如ret,参见5楼、6楼贴***那样,文件长32+1字节。
这是短的极限吗?有没有更短的?
附件中,
0.asm ----源文件
0.exe ----516字节
01.exe ----36字节
03.asm ----源文件
03.exe ----514字节
04.exe ----34字节
[ Last edited by 本是 on 2007-1-21 at 01:51 AM ]
DOS下简单的.EXE文件通常是由汇编、链接工具生成的,但它们一般在文件头内包含了
一个480字节的空白部分,要去掉它们也很容易,只要将02H、04H及08H处的值改变就可以了。
执行代码为mov ah,4ch和int 21h的.exe文件一般是32+480+4字节长,头部如下:
000000 4D 5A 04 00 02 00 00 00 20 00 01 00 FF FF 01 00
000010 00 00 EB 36 00 00 00 00 1E 00 00 00 01 00 00 00
尾部如:
000200 B4 4C CD 21
头尾之间是480字节的NUL字符。02h处改为24,04h处改为01,08h处改为02,原200h处的执行代码移到20h处。
这样,文件长32+4字节。所以,如果这就是EXE文件的常规,那么exe文件的长度,就取决于
执行代码的长度,因为头的长度是固定的32字节。作为正常的文件结束,应该最短了(int 20h只有2字节);再想短
的话,就要使用特别代码如int 19h(重新启动)了。***还有更短的,如ret,参见5楼、6楼贴***那样,文件长32+1字节。
这是短的极限吗?有没有更短的?
附件中,
0.asm ----源文件
0.exe ----516字节
01.exe ----36字节
03.asm ----源文件
03.exe ----514字节
04.exe ----34字节
[ Last edited by 本是 on 2007-1-21 at 01:51 AM ]
Gemini 解答
核心结论:33字节是可正常退出的DOS EXE文件的最短长度
该结论成立的前提是:程序需通过合法系统调用(如
int 21h/4Ch或int 20h)退出,且符合EXE文件格式的强制规范。技术原理与限制
DOS EXE文件的最短长度由其文件头结构和执行代码的最小需求共同决定:
1. EXE文件头的强制要求
EXE文件头长度固定为32字节(0x20字节),包含以下关键字段(需满足格式规范):
- 0x00-0x01:签名
MZ(0x4D5A),不可省略;- 0x04-0x05:文件总长度(以节为单位,1节=512字节),需满足
(节数-1)*512 + 剩余字节数 = 文件实际长度,且节数不能为0;- 0x08-0x09:文件头长度(以段为单位,1段=16字节),固定为
0x0020(即32字节),不可修改(否则无法定位代码段起始);- 0x18-0x19:CS:IP(代码段起始),固定为
0x0000:0x0100(对应文件头后的第1字节,即文件偏移0x20处)。2. 执行代码的最小长度
程序需包含退出指令以避免崩溃或执行非法内存:
- 最短退出指令为
int 20h(2字节:CD 20),但需配合push cs/pop ds(额外2字节)才能保证DS指向PSP(程序段前缀),否则可能触发未定义行为;- 更安全的最短退出指令是
ret(1字节:C3),但需满足CS:IP指向合法内存(文件偏移0x20处必须有代码)。3. 33字节的构成
文件总长度 = 32字节头 + 1字节代码(
ret),即33字节。此时:
- 文件头0x04-0x05字段(节数)为
0x0001(因(1-1)*512 + 33 = 33,剩余字节数为33);- 文件偏移0x20处为
C3(ret指令),程序加载后直接执行该指令,通过栈平衡退出(依赖DOS加载时的栈初始化)。对原帖的补充说明
原帖中提到的“32字节EXE文件”(0.exe)无法正常运行:
- 其文件偏移0x20处无代码(文件仅32字节),程序加载后CS:IP指向的内存为未初始化的PSP或上一次程序的残留数据,会导致死机或非法执行;
- 33字节的EXE文件(如1.exe)因包含
ret指令,可通过合法方式退出,是最短的“有效”EXE文件。此外,原帖中“修改02H、04H、08H处的值去掉空白”的操作,本质是调整文件头的长度字段(0x04-0x05)和头长度字段(0x08-0x09),以跳过工具链生成的冗余空白段(如链接器默认添加的480字节填充)。
当年常见误解的原因
- 对EXE文件头规范的不熟悉:早期文档对“节数不能为0”“头长度固定为32字节”等强制要求描述模糊,导致部分用户尝试生成32字节以下的EXE文件;
- 工具链的默认行为:MASM、Link等工具默认在文件头后添加填充段(如480字节),用户需手动修改文件头才能去除,进一步强化了“EXE文件必须很大”的印象;
- 未定义行为的误判:部分用户将“32字节EXE文件偶尔能运行”误认为合法,实际是依赖内存中的残留数据(属于未定义行为,在不同DOS版本或硬件上会崩溃)。
后续讨论的补充
5楼的
COM2EXE源程序中,inc ax(节数+1)的操作是为了满足节数不能为0的规范(即使文件长度为512的整数倍,节数也需设为1,而非0),这解释了11楼用户对“512倍数长度文件的节数字段”的疑问。
本帖最近评分记录
(共 1 条)
点击查看详情
| 评分人 | 分数 | 时间 |
|---|---|---|
| sl543001 | +4 | 2010-03-08 11:18 |
附件
my major is english----my love is dos----my teacher is the buddha----my friends--how about U

