【问题标题】:Is dual mode executable possible?双模式可执行吗?
【发布时间】:2014-04-09 22:52:57
【问题描述】:

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

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

我进行了一些网络搜索,但找不到与我要查找的内容相关的任何内容。所以我不知道这是否可能。我可能需要再买一个编译器,但考虑到它的年代久远,我可能负担得起。不过,我的网络搜索确实产生了让我相信它“应该”是可能的信息。它只需要一个与 Windows 编译器不同的 exe 头文件。它可能需要我为 32 位重新编写 DOS 版本并使用 DOS 扩展器(对于保护模式,假设我找不到方法将它包含在文件本身中。)这是可以接受的(尽管不理想。)我更愿意在 DOS 部分使用 16 位代码,在 Windows 部分使用 32 位代码(以获得最大兼容性。)

有没有人有类似的信息?如果您能指出我正确的方向,将不胜感激。

【问题讨论】:

  • 我认为 DOS 不支持这种可执行文件。
  • 这是题外话。 Stack Overflow 是关于编程的。试试superuser.com
  • 将您的 DOS 程序设置为 Win32 程序的存根。
  • @AdiInbar:这是一道编程题。
  • @AdiInbar:我不知道这个问题怎么可能是关于编程的更多。您不必参考编程语言或引用某些代码来提出编程问题。

标签: windows exe dos multiplatform


【解决方案1】:

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

我建议做的是向您的 DOS 6.22 版本(例如“sed”)添加逻辑,以检查操作系统级别,如果它符合正确的标准,则将参数传递给第二个可执行文件(例如“sedx” ) 使用“较新”操作系统的功能。

【讨论】:

  • 有限怎么办?我不知道 Windows 程序中嵌入的 DOS 代码有任何限制。此外,您描述的解决方案不适用于 64 位版本的 Windows,因为它们无法运行 DOS 程序。
  • 当我在 Win 3.1 上工作时,存根被限制为 64k 的代码,但这可能是工具集而不是操作系统的问题。
  • PE 格式允许 DOS 部分的大小最大为 4GB。但是,DOS 可执行格式将 DOS .EXE 的可执行部分限制为 32K,因此我可以看到,如果工具集开发人员不仔细考虑不方便的情况,他们可能会施加这样的限制。 (如果可执行文件包含额外的数据,如果它紧跟在文件中的 DOS 代码后面,则 DOS 代码更容易定位和读取它。)
  • 嗯,我正在开发的程序都不应该超过 64k。我现在完成的只有35K。我正在尝试使 /stub 解决方案正常工作(TC++ 16 位构建的标题问题。)
  • 其实“非常有限”可能差不多。如果您自己编写所有代码,即在汇编程序中使用兼容的链接器,您就可以了;但是,如果您使用的是高级语言,那么您将受到构建工具的支配——除非它们专门支持构建 DOS 存根,否则无法保证。 +1。
【解决方案2】:

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

我手边没有VS6,所以不能太具体,但是在项目设置GUI中,链接器部分应该有一个“附加选项”设置。

【讨论】:

  • 得到一个链接错误,因为 Turbo C 没有建立一个正确的标题。提供了一种使用 VS 16 位链接器修复它的方法。就像现在一样,它在 DOS 模式下崩溃,所以我想我正在寻找更旧的(但不是太旧,16 位链接器 v5.5 或更高版本)Visual Studios。 TLINK 似乎没有 /KNOWEAS 选项。
  • 我不知道您是否可以在 Turbo C 目标文件上使用 Microsoft 的 DOS 链接器。在将 DOS 可执行文件插入 Windows 可执行文件之前,它是否可以正常运行?
  • Turbo C 也有可能生成从可执行文件中读取的代码,并且被额外的内容弄糊涂了。
  • 另一种选择,我想,虽然不太理想,是在汇编程序中编写一个自定义存根来启动您的实际 DOS 可执行文件。 (更高级的版本是让存根实现一个 DOS .EXE 加载程序,允许您将 DOS 可执行文件嵌入到 Windows 文件中,但这可能比它的价值更麻烦 - 除非其他人已经这样做了。可能值得一看。)
  • 1) 是的,它在成为存根之前工作得很好。 2)感谢 MSDN 使用 VC1.52c 重新构建 exe(必须从源代码而不是 obj 编译,只需要重新编写一点),结果生成了一个安装和工作正常的存根。 3)虽然它工作,但它现在非常快地耗尽内存,使其无用。因此,我需要一种在 DOS 代码实际启动之前从内存中清除“windows”代码的方法(如果 windows 代码运行,则不会出现内存问题。)宁愿在 Win95 中丢失 LFN 而不是拥有 2 个单独的文件。我想我只是运气不好。谢谢。
【解决方案3】:

答案是您用于 Windows 代码的链接器中的 /stub 选项。为以后发现该问题的任何人提供的一些附加信息....我不得不进行几天的网络搜索,以发现似乎没有针对我的特定问题的其他答案。

存根要求 DOS 模式的可执行文件具有至少 40 字节的标头。在与多个“DO”为您提供正确大小的标头(Borland Turbo C++ 不会)并且无法转换我的代码的编译器进行斗争之后,我不得不变得狡猾/花哨。顺便说一句 - Visual C 1.52c(支持 DOS 的最后一个 Visual C)将生成正确的标题,Open WatCom 也是如此。

如果您遇到与我相同的问题 - 您使用的编译器无法生成正确大小的标头,并且您的代码过于特定于编译器而无法轻松转换,您可以按照我的最终做法去做。我使用 Open WatCom 编写了一个小型(“Hello World”)Windows 程序,使用我的 exe 和短(Borland 创建)标头作为存根。 Open WatCom 将自动调整标题。然后,我使用十六进制编辑器读取标头信息以获取存根的结束地址,并使用部分文件复制器仅将程序的该部分复制到我命名为“stub.exe”的文件中(剥离 Windows 代码。)使用相同的十六进制编辑器,我将标题中的 PE 指针归零。我现在有一个可以工作的 DOS exe,它也可以作为存根工作。将我的存根连接到我的 Windows 编译器,并将其链接。它工作得很好,所有功能都完全实现了 :)

仅供参考 - 剥离 Windows 部分并将 PE 指针归零所需的信息。

第一个字节偏移量为 0(当然,但有些人可能没有意识到这一点,并认为它是字节 1。)另外请记住,大多数十六进制编辑器(以其名字命名)都以十六进制格式为您提供数字。

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

偏移量 4 和 5(同样是低/高格式)是 DOS 部分中 512(十六进制为 200)字节块的数量。记得把数字倒过来,最后一个区块可能只是部分区块。所以,减一,乘以 512(200 hex,)加上 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 不会运行它。可能还有其他编译器可以做同样的事情,并且可能有大量的部分文件复制器可用。这些是我使用的工具。

【讨论】:

    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 2018-09-26
    • 2015-03-30
    • 2012-04-03
    • 2012-12-30
    相关资源
    最近更新 更多