环境是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
,但我收到的结果是:
文件无法转换
出了什么问题?
答案 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
指令引用段DATA
,DATA
的值取决于MS-DOS加载可执行文件的位置。这需要在可执行文件中进行重定位,以便MS-DOS知道在加载时使用正确的段值修改该值。
要创建一个既可以使用exe2bin
又可以生成可用的.COM文件的可执行文件,您需要执行以下操作:
ORG 100h
指令ORG 100h
指令后面的入口点的符号,使其位于偏移100h处。END
指令的参数提供,以便它成为入口点。ORG 100h
指令之前必须没有定义任何内容(否则exe2bin
会将其丢弃)。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调用来退出程序,否则您的代码将在打印消息后继续执行指令。在您的原始可执行文件中,这将是随机未初始化的数据,在上面的程序中,它将被解释为x86机器代码的字符串HelloWorld!$
。
正如rcgldr发布的那样,您可以跳过exe2bin
步骤并让链接器使用/TINY
选项直接生成.COM文件。使用此选项时,上面给出了与创建.COM文件相同的规则。