![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-07 16:20 |
共 48,041 主题排行 / 350,128 发帖 / 今日 3 篇 / 48,252 会员排行 |
| DOS开发编程 & 发展交流 (开发室) » 33字节DOS EXE文件,最短了? |
| 可打印版本 3,245 / 12 |
| 第1楼 本是 | 发表于 2007-01-16 12:12 |
| 银牌会员 发帖 790 积分 2,227 | |
|
33字节DOS EXE文件,最短了? 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 ] 附件 COOLEXE.RAR (533 bytes) |
|
| 第2楼 electronixtar | 发表于 2007-01-17 10:54 |
| 铂金会员 发帖 2,672 积分 7,493 | |
|
34字节,汗~~~
|
|
| 第3楼 enjoyer | 发表于 2007-01-19 09:32 |
| 中级用户 发帖 140 积分 351 | |
|
本是兄解释一下为什么把04h,和08h处的值改变就能去掉中间的空白部分.
是程序加载时不分配这480字节吗? 最好是在可执行文件中去掉啊. |
|
| 第4楼 本是 | 发表于 2007-01-20 11:11 |
| 银牌会员 发帖 790 积分 2,227 | |
Originally posted by enjoyer at 2007-1-19 09:32: 比如下面的文件: 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 EXE文件头的第04h、06h处word分别存储着EXE文件长度的200h的模及商(不能为0,所以要+1),08h处word存储文件头长度(以节为单位)以确定载入模块的开始位置,其它内容因此次修改简单并不涉及: 04 00 --> 0004:4字节 02 00 --> 0002:(2-1)*512字节;4+(2-1)*512=516字节 20 00 --> 0020:20h*16=512字节 现在截去20h--200h之间的部分,文件长 mod 512=36,文件长/512+1=1, 文件头长32/16=2,改后为 000000 4D 5A 24 00 01 00 00 00 02 00 01 00 FF FF 01 00 000010 00 00 EB 36 00 00 00 00 1E 00 00 00 01 00 00 00 000020 B4 4C CD 21 查查EXE文件头的结构就应该清楚了。 |
|
| 第5楼 本是 | 发表于 2007-01-21 01:20 |
| 银牌会员 发帖 790 积分 2,227 | |
|
再给个COM2EXE的转换程序,大家可以对照学习EXE与COM的文件差别。
所附源程序中第1行及相关部分为我所加,你可以根据需要把xtra_bytes equ后面的数字256改为0到65500之间的任何值。试一试吧! xtra_bytes equ 256 ;0--65500,so long as you need!!! .286 Code SEGMENT para PUBLIC 'CODE' Assume CS:Code, DS:Code ORG 100h ;========================================================== cr equ 10 lf equ 13 ;========================================================== Start: Call Header ;logo Call CmdLine cmp al,-1 je _usage Call OpenRFile ;open readfile cmp al,-1 je _norfile Call OpenWFile ;open writefile cmp al,-1 je _nowfile Call HeadOn ;write header _closewfile: Call CloseWFile ;close writefile jmp _closerfile _nowfile: Call NoFile _closerfile: Call CloseRFile ;close readfile jmp _ende _norfile: Call NoFile jmp _ende _usage: Call Usage ;display usage _ende: Call Footer ;display --------------------- mov ax,4c00h int 21h ;========================================================== HeadOn PROC near pusha mov cx,32+xtra_bytes ;bytes mov ah,40h ;write to file mov bx,WFileHandle ;handle of file lea dx,exe_header ;data: where at int 21h jc headon_fail headon_lop: mov ah,3fh ;read mov bx,RFileHandle ;handle mov cx,63000 ;bytes lea dx,loadword ;where at int 21h or ax,ax ;0 bytes ? !!!! jz headon_end ; !!!! add filesize,ax mov cx,ax ;bytes mov ah,40h ;write mov bx,WFileHandle ;handle lea dx,loadword ;where at int 21h jc headon_fail jmp headon_lop headon_end: add filesize,32+xtra_bytes xor cx,cx mov dx,2 ;where at (cx:dx) mov ax,4200h ;move filepointer to (from files begin) mov bx,WFileHandle ;handle int 21h mov ax,filesize and ax,511 mov loadword,ax ;length mod 512 mov ax,filesize mov cl,9 shr ax,cl ;div 512 inc ax mov ,ax ;pages mov cx,4 ;bytes mov ah,40h ;write mov bx,WFileHandle ;handle lea dx,loadword ;where at int 21h lea dx,headon_ Call Print popa ret headon_fail: lea dx,headon_fail_ Call Print CALL FileName popa mov al,-1 ret headon_ db 'CREATED EXE-FILE',cr,lf,'$' headon_fail_ db 'CANNOT WRITE TO $' exe_header db 'MZ' ;offset 00 (EXE-signature) dw 0,0 ;bytes on last page, pages dw 0 ;relocations dw 2+(xtra_bytes shr 4) ;size of header in paragraphs dw 1000h,-1 ;minimum, maximum memory dw 0fff0h,0fffeh ;ss,sp values (ss=PSP) dw 0 ;checksum dw 100h,0fff0h ;ip,cs values (cs=PSP) dw 1ch ;offset to reloc table dw 0,0,0 ;overlay number, 0,0 (fill-ups) db xtra_bytes dup(0) HeadOn ENDP ;========================================================== CloseRFile PROC near pusha mov bx,RFileHandle mov ah,3eh int 21h popa ret CloseRFile ENDP ;========================================================== CloseWFile PROC near pusha mov bx,WFileHandle mov ah,3eh int 21h popa ret CloseWFile ENDP ;========================================================== NoFile PROC near pusha lea dx,nofile_ Call Print Call FileName popa ret nofile_ db 'CANNOT OPEN FILE $' NoFile ENDP ;========================================================== OpenRFile PROC near pusha mov dx,82h ;asciiz = cmdline mov ax,3d00h ;open it for read int 21h jc openrfile_fail mov RFileHandle,ax lea dx,openrfile_ Call Print Call FileName popa ret openrfile_fail: popa mov al,-1 ret openrfile_ db 'OPENED FILE $' OpenRFile ENDP ;========================================================== OpenWFile PROC near pusha xor ah,ah mov al,ds:80h mov di,ax mov ds:,'XE' mov byte ptr ds:,'E' mov dx,82h ;asciiz = cmdline mov ah,3ch ;open it for write mov cx,0 ;attribute int 21h cmp ax,0 je openwfile_fail mov WFileHandle,ax lea dx,openwfile_ Call Print Call FileName popa ret openwfile_fail: popa mov al,-1 ret openwfile_ db 'OPENED FILE $' OpenWFile ENDP ;========================================================== CmdLine PROC near pusha xor ah,ah mov al,ds:80h cmp ax,6 ;less than 5 chars (cmd-LINE) incl. ret? jl cmdline_fail mov di,ax mov word ptr ds:,'$'*256 popa ret cmdline_fail: popa mov al,-1 ret CmdLine ENDP ;========================================================== Header PROC near pusha lea dx,header_ Call Print popa ret header_ db cr,lf db '--==-- COM2EXE --==-- by HENDR璛 of OBSESSION',cr,lf,'$' Header ENDP ;========================================================== Footer PROC near pusha lea dx,footer_ Call Print popa ret footer_ db '--==**==-- COM2EXE --==**==--',cr,lf,'$' Footer ENDP ;========================================================== Usage PROC near pusha lea dx,usage_ Call Print popa ret usage_ db 'USAGE: C2E PROGRAM.COM',cr,lf,'$' Usage ENDP ;========================================================== Print PROC near mov ah,09h int 21h ret Print ENDP ;========================================================== Return PROC near pusha lea dx,return_ Call Print popa ret return_ db cr,lf,'$' Return ENDP ;========================================================== FileName PROC near pusha mov dx,82h Call Print Call Return popa ret FileName ENDP ;========================================================== filesize dw 0 RFileHandle dw ? WFileHandle dw ? loadword dw ? ;========================================================== Code ENDS END Start [ Last edited by 本是 on 2007-1-21 at 01:22 AM ] |
|
| 第6楼 本是 | 发表于 2007-01-21 01:43 |
| 银牌会员 发帖 790 积分 2,227 | |
|
通过C2E把COM转换成EXE的实验,我发觉EXE文件最小的长度应该是33字节!
先把5楼的首行equ后的256改成0,存为c2e.asm, masm c2e; link c2e; exe2bin c2e 再在debug下生成0、1、2、3、4字节的COM文件: debug n0.com rcx 0 w a100 ret n1.com rcx 1 w a100 int 20 n2.com rcx 2 w a100 push cs pop ds ret n3.com rcx 3 w a100 mov ah,4c int 21 n4.com rcx 4 w q 然后 c2e 0.com c2e 1.com c2e 2.com c2e 3.com c2e 4.com 可以得到32、33、34、35、36字节的EXE文件(见本楼附件)!!!再分别运行 1.exe 2.exe 3.exe 4.exe 通过! 不要在真实机纯DOS下运行0.exe,要死机的!或者会重复运行刚刚运行过的执行文件的内存映象----因为所有的运行都是在内存中进行的!!!而32字节的EXE文件载入后无运行代码进入内存,而它又指示运行文件头后的代码,而此处的代码就自然是上一次运行过的代码喽! [ Last edited by 本是 on 2007-1-21 at 02:14 AM ] 附件 01234.RAR (472 bytes) |
|
| 第7楼 enjoyer | 发表于 2007-01-21 10:03 |
| 中级用户 发帖 140 积分 351 | |
Originally posted by 本是 at 2007-1-20 11:11: 本是兄果然出手不凡, 佩服.不过我还有一点疑问就是为什么一定要是36不是20个字节呢? 上面三行去掉中间一行, 第一行改为: 000000 4D 5A 14 00 01 00 00 00 01 00 01 00 FF FF 01 00 [ Last edited by enjoyer on 2007-1-21 at 10:06 AM ] |
|
| 第8楼 本是 | 发表于 2007-01-22 04:58 |
| 银牌会员 发帖 790 积分 2,227 | |
|
这一点我已经试验并思考多次:EXE文件头02h和14h的word值都改成负值、再把执行代码藏在文件头的某些位置,但都不成功。原因可能是EXE格式本身规定所致:我用俄罗斯跟踪工具INSIGHT跟踪的结果是----如果填入0、0FFFEh,并把C3填入文件头的第1Fh字节,载入时预备运行位置是在无符号值0FFFEh而不是有符号值的-1处!也就是说执行代码位置只能为正,为0时执行内存映象----通常为上次运行过的程序映象!如果我的观察没有出错,确实EXE文件最小值就是33字节!!!
[ Last edited by 本是 on 2007-1-22 at 04:59 AM ] |
|
| 第9楼 nyuser | 发表于 2007-01-25 01:37 |
| 新手上路 发帖 2 积分 4 | |
|
强! 编程是艺术啊!!!
|
|
| 第10楼 Jneny | 发表于 2007-01-25 01:52 |
| 高级用户 发帖 318 积分 686 | |
|
我要学习到这个地步得多少年呀,想下就晕
|
|
| 第11楼 atoms | 发表于 2010-03-07 14:59 |
| 初级用户 发帖 28 积分 182 | |
|
aaaaa 当文件字节为512的陪数时,02h为是0,04h为1?而不是为2,1-1=0*512不不成立了
|
|
| 第12楼 本是 | 发表于 2010-03-08 10:18 |
| 银牌会员 发帖 790 积分 2,227 | |
|
请再看看5楼源程序中的这一段:
mov ax,filesize and ax,511 mov loadword,ax ;length mod 512 mov ax,filesize mov cl,9 shr ax,cl ;div 512 inc ax mov ,ax ;pages 注意变红的行,它保证不能为零! |
|
| 第13楼 sl543001 | 发表于 2010-03-08 11:29 |
| 中级用户 发帖 225 积分 499 | |
|
坚决支持.
|
|
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |