简体   繁体   中英

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

The environment is MS-DOS system.
I have a simple h.asm code for hello world output using dos 9# call

.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

Using MASM command: masm h.asm I have got the file h.obj. Then link h.obj I have got the h.exe file.

Now I want to obtain the .com file of the .exe file using command exe2bin h.exe , but the result I received is:
File cannot be converted
What went wrong?

For real (16 bit) mode assembly, depending on the tool set, you may be able to use TINY model instead of using exe2bin.

Batch file for release build using Microsoft 16 bit toolset:

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

Batch file for debug (codeview) build:

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

Example MSDOS / MASM (ML.EXE) 6.11 source code:

        .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 bit toolset and 16 bit programs will run in console mode on 32 bit versions of Windows. For 64 bit versions, use a virtual PC or perhaps DOSBOX.

The program exe2bin requires that the .EXE file you're converting either has an entry point of 0000:0100 or no entry point at all. In the former case the the executable can't have any segment relocations, and the result is normally something that can be loaded by MS-DOS as a .COM file. In addition the .EXE file can't have a stack, and must have a load size 64K or less.

The direct reason why exe2bin is failing is because you have entry point of something like 0001:0000 , where the segment part is relative to the start of the executable and adjusted by the location in memory where MS-DOS loads the executable. (So for example if MS-DOS loads the executable at 1234:0000, then entry point is 1235:0000.) This isn't suitable for a .COM file since MS-DOS simply copies the .COM file into memory and jumps an offset 0100 in the segment. (So if MS-DOS loads the .COM file at 1234:0000, it jumps to 1234:0100).

Another problem with your executable is that even if it used the correct entry point it also a has a segment relocation. The MOV AX, DATA instruction references the segment DATA , and the value of DATA depends on where MS-DOS loads the executable. This requires a relocation in the executable so MS-DOS knows to modify the value with the correct segment value when it loads it.

To make an executable that will both work with exe2bin and produce a usable .COM file you need the following things:

  1. An ORG 100h directive at the start of your program
  2. A symbol defining the entry point placed after the ORG 100h directive so that it's located at offset 100h.
  3. The entry point symbol must be supplied as the argument to END directive so it becomes the entry point.
  4. There must be only one segment in which everything lives.
  5. There must be nothing defined before the ORG 100h directive (otherwise it will be discarded by exe2bin ).
  6. The size of the executable, as loaded in memory must be less than 64K. This includes the 256 bytes taken up by the ORG 100h directive. In other words everything must live in the same 64K segment.

For example, you can turn your program into something can produce a working .COM file by rewriting it like this:

    .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.

Note that I've added an MS-DOS call to exit the program, otherwise your code would've continued to execute instructions after printing the message. In your original executable this would've been random uninitialized data, in the program above it would be the string HelloWorld!$ as interpreted as x86 machine code.

As rcgldr posted you can skip the exe2bin step and have the linker produce a .COM file directly by using the /TINY option. The same rules given above for creating a .COM file apply when using this option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM