在DOS系统下用exe2bin将.exe文件转换成.com文件

convert .exe file to .com file with exe2bin in DOS system

环境为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,但我收到的结果是:
无法转换文件
出了什么问题?

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

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

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

用于调试 (codeview) 构建的批处理文件:

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。

程序 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 段中。

例如,您可以像这样重写您的程序,使其变成可以生成工作 .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 调用以退出程序,否则您的代码将在打印消息后继续执行指令。在您的原始可执行文件中,这将是随机未初始化的数据,在上面的程序中,它将是字符串 HelloWorld!$ 被解释为 x86 机器代码。

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