在DOS系统中使用exe2bin将.exe文件转换为.com文件

时间:2017-03-15 11:51:39

标签: assembly exe typeconverter

环境是MS-DOS系统 我有一个简单的h.asm代码,用于使用dos 9#call

进行hello world输出
.386
DATA    SEGMENT USE16
MSG     DB 'HelloWorld!$'
DATA    ENDS

CODE    SEGMENT USE16
ASSUME  CS:CODE,DS:DATA
BEG:    MOV AX,DATA
MOV     DS,AX
MOV     DX,OFFSET MSG
MOV     AH,9
INT     21H
CODE    ENDS
END     BEG

使用MASM命令: masm h.asm我有文件h.obj。然后link h.obj我有h.exe文件。

现在我想使用命令获取.exe文件的.com文件 exe2bin h.exe,但我收到的结果是:
文件无法转换
出了什么问题?

2 个答案:

答案 0 :(得分:1)

对于实际(16位)模式汇编,根据工具集,您可以使用TINY模型而不是使用exe2bin。

使用Microsoft 16位工具集发布版本的批处理文件:

ml /c %1.asm
link /tiny %1.obj;

debug(codeview)build的批处理文件:

ml /Zi /c %1.asm
link /CO /tiny %1.obj;

示例MSDOS / MASM(ML.EXE)6.11源代码:

        .286
        .model  tiny,c
        .code
        org     0100h
main    proc    far
        lea     dx,msg0
        mov     ax,0900h                ;display msg
        int     21h
        mov     ax,04c00h               ;exit
        int     21h
msg0    db      'msdos tiny asm example',0dh,0ah,'$'
main    endp
        end     main

Microsoft 16位工具集和16位程序将在32位版本的Windows上以控制台模式运行。对于64位版本,请使用虚拟PC或DOSBOX。

答案 1 :(得分:1)

程序exe2bin要求您要转换的.EXE文件的入口点为0000:0100或根本没有入口点。在前一种情况下,可执行文件不能有任何段重定位,结果通常可以由MS-DOS作为.COM文件加载。此外,.EXE文件不能有堆栈,并且必须具有64K或更小的加载大小。

exe2bin失败的直接原因是因为你有0001:0000之类的入口点,其中段部分相对于可执行文件的开头,并由内存中MS的位置调整-DOS加载可执行文件。 (例如,如果MS-DOS在1234:0000加载可执行文件,则入口点为1235:0000。)这不适用于.COM文件,因为MS-DOS只是将.COM文件复制到内存中并跳转在段中偏移0100。 (因此,如果MS-DOS在1234:0000加载.COM文件,则跳转到1234:0100)。

您的可执行文件的另一个问题是即使它使用了正确的入口点,它也有一个段重定位。 MOV AX, DATA指令引用段DATADATA的值取决于MS-DOS加载可执行文件的位置。这需要在可执行文件中进行重定位,以便MS-DOS知道在加载时使用正确的段值修改该值。

要创建一个既可以使用exe2bin又可以生成可用的.COM文件的可执行文件,您需要执行以下操作:

  1. 程序开头的ORG 100h指令
  2. 定义ORG 100h指令后面的入口点的符号,使其位于偏移100h处。
  3. 必须将入口点符号作为END指令的参数提供,以便它成为入口点。
  4. 一切都必须只有一个部分。
  5. ORG 100h指令之前必须没有定义任何内容(否则exe2bin会将其丢弃)。
  6. 在内存中加载的可执行文件的大小必须小于64K。这包括ORG 100h指令占用的256个字节。换句话说,一切都必须存在于相同的64K段中。
  7. 例如,您可以将程序转换成可以生成有效的.COM文件,方法是重写它:

        .386
                                                   ; Requirements implemented
    CODE SEGMENT USE16                             ; 4. 
        ORG 100h                                   ; 1. 
    
        ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE    ; 4. 
    
    BEG: MOV    DX,OFFSET MSG                      ; 2.
        MOV     AH,9
        INT     21H
    
        MOV     AX,4C00H ; exit the program
        INT     21H     
    
    MSG DB 'HelloWorld!$'                          ; 4. 5.
    
    CODE ENDS
    
        END     BEG                                ; 3.
    

    请注意,我已经添加了一个MS-DOS调用来退出程序,否则您的代码将在打印消息后继续执行指令。在您的原始可执行文件中,这将是随机未初始化的数据,在上面的程序中,它将被解释为x86机器代码的字符串HelloWorld!$

    正如rcgldr发布的那样,您可以跳过exe2bin步骤并让链接器使用/TINY选项直接生成.COM文件。使用此选项时,上面给出了与创建.COM文件相同的规则。