双模可执行文件是否可行?

时间:2014-04-09 22:52:57

标签: windows exe dos multiplatform

有点历史...我有3个系统,我花时间,DOS 6.22系统,Windows 95系统和现代Windows 7(64位)系统。当我升级到Win7-64时,我最喜欢的一些命令行实用程序停止工作,所以我决定自己重新编写它们。我只有2个编译器是Borland Turbo C ++ 3.0和Visual Studio 2008,它们可以很好地构建2个版本,DOS 16位和32位Windows 7(我猜也可以构建64位版本)。 )问题出在我的Win95系统上。 DOS版本在那里运行良好,但由于我花时间在Win7版本中支持LFN,我想用它的Win95系统。因此,经过大量的研究,我发现并购买了Visual Studio 6(最后一个根据我研究的Win95支持)复制代码(当然必须重写部分)并且它编译得很好,并且工作正常:)

下次我必须在DOS模式下启动Win95系统时出现问题。程序停止工作(当然,因为Win95没有加载)。我真的不想安装2个程序副本(需要2个不同的文件名),所以我希望有一种方法可以将2个版本链接到一个文件中。如果我在DOS中执行它,而不是说它需要窗口,它只会跳转到程序的DOS部分。这样,它将是一个单独的程序,如果加载Win95则支持LFN,如果没有加载Win95则不支持。由于Win95版本在Win7-64中也可以正常工作,它可能还会生成一个适用于所有3个系统的单一版本(这将是一个额外的好处。)

我做了一些网络搜索,找不到与我正在寻找的内容密切相关的东西。所以我不知道它是否可能。我可能必须得到另一个编译器,但考虑到它将有多大,我可能负担得起。我的网络搜索确实产生了让我相信它“应该”成为可能的信息。它只需要一个不同于一个Windows编译器输入的exe头。它可能需要我重写DOS版本为32位并使用DOS扩展器(对于保护模式,假设我找不到方法将它包含在文件本身中。)这是可以接受的(虽然不理想。)我宁愿在DOS部分使用16位代码,在Windows部分使用32位代码(为了最兼容。)

有没有人有关于这样的事情的任何信息?如果你能指出我正确的方向,我们将不胜感激。

3 个答案:

答案 0 :(得分:3)

我不知道它是否在Windows 7可执行文件中继续存在,但在Win95中,可执行文件(EXE)实际上有两个入口点 - 一个"正常" DOS会找到的,Windows会使用的第二个。 DOS入口点通常是一个非常简单的默认值,只会打印"这是一个Windows程序"并退出。您实际上可以覆盖此默认值,并让链接器使用您自己的代码,但它非常有限。

我建议做的是为DOS 6.22版本添加逻辑(例如" sed"),这将检查操作系统级别&如果它符合正确的标准,将参数传递给第二个可执行文件(例如" sedx"),它使用来自"较新的" OS。

答案 1 :(得分:2)

Visual Studio 6的文档描述了/STUB选项here,只需将其指向程序的DOS版本。

我没有VS6方便,所以我不太具体,但在项目设置GUI中,应该有一个"附加选项"设置链接器部分。

答案 2 :(得分:1)

答案是您用于Windows代码的链接器中的/ stub选项。对于后来发现问题的任何人的一些其他信息....我不得不进行几天的网络搜索,发现似乎不是我特定问题的另一个答案。

Stub要求DOS模式可执行文件具有至少40个字节的标头。与多个编译器打架后,#34; DO"给你一个合适大小的标题(Borland Turbo C ++赢了,并且没有能够转换我的代码),我不得不偷偷摸摸/喜欢。顺便说一句 - Visual C 1.52c(支持DOS的最后一个Visual C)会打开一个正确的标题,Open WatCom也是如此。

如果你是我面临同样问题的面孔 - 你使用的编译器不会制作正确的大小标题,并且你的代码太过编译器特定而无法轻松转换,你可以做我最终做的事情。我使用Open WatCom使用我的exe编写了一个小的(#34; Hello World")Windows程序,其中以short(Borland created)标题作为存根。打开WatCom会自动调整标题。然后,我使用十六进制编辑器读取标题信息以获取存根的结束地址,并使用部分文件复制器将该部分程序复制到我命名为" stub.exe"的文件中。 (剥离Windows代码。)使用相同的十六进制编辑器,我将标头中的PE指针归零。我现在有一个工作的DOS exe,也可以作为存根。把我的存根带到我的Windows编译器,并将其链接。它工作得很好,所有功能都完全实现了:)

FYI - 剥离Windows部分并将PE指针归零所需的信息。

第一个字节偏移为0(当然,但是有些人可能没有意识到这一点,并认为它的字节为1.)还要记住,大多数Hex编辑器(按照他们的名字)给你的数字十六进制格式。

抵消2& 3,低字节 - 高字节格式的文件DOS部分的最后一个块中的字节数。也就是说,偏移2低,3高。所以拿它们,反转它们,你会得到一个0到511之间的数字(0到1ff,十六进制).0表示使用512(十六进制为200)字节的整个块。

抵消4& 5(再次以低/高格式),是DOS部分中512(十六进制为200)字节块的数量。请记住反转该数字,并且最后一个块可能只是部分块。因此,减去1,乘以512(200十六进制),从2-3添加数字,你有多少字节在DOS部分。由于你从0开始,减去1,你现在知道只复制字节0 - "无论总数是多少"你的存根exe。

偏移量60-61(十六进制3C-3D)是指向代码的PE(或可移植可执行文件)部分的开始的指针(Windows跳转到的部分。)它应该刚刚过去(我的是填充的)用几个零,)代码的DOS部分的结尾。这在当时并不重要,因为我们只是将它们转换为0(PE部分已被剥离。)您可以使用此作为确认您有正确的"结束DOS"虽然选择了偏移。

我使用的工具是: 在http://www.openwatcom.org/index.php/Main_Page打开WatCom      和 零件复制http://www.virtualobjectives.com.au/utilitiesprogs/partcopy.htm

我不知道在哪里找到我使用的十六进制编辑器。我使用CEdit,一个我非常喜欢的DOS程序,但一直无法在网上找到。不得不使用DOSBox,因为Win7不会运行它。可能还有其他编译器做同样的事情,可能还有大量的部分文件复制器。这些是我使用的工具。