我最近发现64位窗口不会运行16位应用程序(在本例中是.com),因为64位窗口没有16位子系统(或者互联网这么说)。我在尝试执行一个调用编辑的.bat文件时遇到了这种情况。
我对x86程序集有相当丰富的经验,但从未编写过在windows下运行的程序(或任何其他操作系统)。由于x86家族的向后兼容性,我从来没有真正关注过我的程序有多大。只要它不使用没有介绍给程序运行的CPU的指令,就没问题。
我的问题是:究竟是什么使代码16、32或64位,是什么触发了16位应用程序显然存在的不兼容问题?
是否有可能拆卸小型16位应用程序并进行一些修改以使其正常工作,或者这真的是不明智的吗?
更新:我并不是在寻找一种方法来运行这些类型的应用程序,即通过模拟器或其他程序来运行,这样我就可以自己工作了。我只想了解使windows接受或拒绝程序的基本机制。
发布于 2013-12-06 20:54:04
要运行“16位应用程序”(在本例中指的是DOS应用程序),Windows需要在VM86模式下设置任务。问题是,这是当CPU处于32位VPAM (虚拟保护地址模式)时工作,这是i386操作系统所使用的,而不是当CPU处于所谓的“长模式”时。amd64 CPU“长模式”只支持运行32位和64位任务。
因此,64位操作系统内核没有选择直接在CPU上运行16位任务,您必须始终使用某种模拟。如果你找到一个能做到这一点的操作系统,它要么内置仿真,要么以32位模式运行,而不是64位模式,或者在32位和64位模式下运行,并在它们之间愉快地切换,我在某个地方读到过一些邪恶的、扭曲的黑客。
从经验来看,使用DOSBOX是你最好的选择。
编辑:Windows如何检测到它无法运行您的代码?
这在很大程度上取决于检测到的程序类型。还有它知道要处理的批处理文件(BAT、CMD)、PIF文件(我认为它们仍然没有杀死它们),最后还有COM和EXE可执行文件。COM的情况很简单:65280字节-最大值.16位MS程序,out。另一方面,EXE文件有特定的文件头:一个用于16位DOS (或Win3.x)部分(关键字: MZ),一个用于32位/64位部分(LE、LX、PE (至少)、a.out和COFF ),其中一些用于OS/2兼容性或仅用于它,另一些则由各种NT变体使用。
发布于 2013-10-15 02:32:29
其实有不止一个问题。首先,处理器对每个"bitness“都有不同的操作模式。但是,每种类型的应用程序都需要一个超出bitness的执行环境。它被称为应用程序二进制接口 (ABI)。例如,.com文件包含需要真正模式DOS环境的代码,包括某些硬件。早期版本的windows需要启动类似于DosBox的东西才能运行它们。每种类型的可执行文件都可能不需要完整的硬件仿真,而是需要大量的代码与主操作系统进行交互。因此,对于每种类型的可执行文件,操作系统都会检查需要什么样的运行时环境,并且拒绝运行可执行文件,除非它能够提供正确的环境。
发布于 2013-12-14 03:45:54
我的问题是:究竟是什么使代码16、32或64位,是什么触发了16位应用程序显然存在的不兼容问题?
很明显的答案是:取决于使用8,16,32或64位寄存器的程序。显然但不正确:在MS中运行的程序可以使用8,16,或32位寄存器,如果处理器支持这些寄存器的话。或者,Windows程序除了使用32位寄存器和(如果处理器和操作系统支持的话) 64位寄存器之外,还可以使用(实际上也使用)8和16位寄存器。
我认为问题应该是:究竟是什么使程序在DOS或Windows 32位或Windows 64位下运行。
第一,可执行文件的结构。32位或64位Windows可执行文件与16位可执行文件不同.Windows使用所谓的“可移植可执行”(PE的缩写)。MS使用.COM文件(从CP/M继承)和.EXE文件(也称为MZ可执行文件)。
第二个:其中一个程序存储在内存中并开始执行,那里有一些程序期望的环境,例如,由一些特殊指令访问的大量函数调用,比如INT,它们负责执行不同的任务,从将一个字符输出到控制台,到打开和读取文件等等。
第三代:MS应用程序期望内存中的某些结构位于特定的内存地址;例如屏幕内存。此外,它还期望某些I/O设备存在于特定的I/O地址。许多所谓的“不良行为”应用程序不使用BIOS或DOS在屏幕上打印,而是直接写入屏幕内存,以获得更快的输出。我记得在Turbo,Turbo,或者可能是Turbo编译器中设置了一个设置,让程序员选择控制台输出函数通过BIOS,或者直接进入硬件。
第四:程序期望处理器以一种特定的方式运行。16位DOS程序的设计是为了使用所谓的实模式的x86处理器,这种模式强加了它的特殊的内存地址的视觉,以命名这种模式的最独特的特点。随着将处理器置于保护模式的32位OS的到来,实模式程序无法工作,因为内存地址在保护模式下工作的方式与它在实模式下的工作方式有很大的不同。
一个愿意运行MZ可执行文件的操作系统需要--某种类型的加载器来处理这些文件(为了遵守第一点)--和一个必须模仿应用程序应该工作的文件到中的环境(以遵守其余的要点)。在Linux中,这些组件是他们所称的特性的一部分(这是Linux从其他操作系统(如FreeBSD )运行代码的一种方式,前提是这段代码适用于两个平台上相同的处理器)。在Windows世界中,这被称为子系统。例如,Windows和Windows7有Win32子系统和DOS子系统。Windows的古老版本(可能是WindowsNT3.5或NT4.0)也具有 OS/2 特性,能够运行OS/2 16位文本模式应用程序。
因此,您的Windows操作系统需要批准子系统来运行为另一个操作系统设计的代码,比如MS。但处理器必须以任何可能的方式提供帮助。这是因为x86平台在80386中引入了8086虚拟模式:以便能够创建处理器行为与实际模式8086非常相似的任务。
因此,在CPU本身的帮助下,审批加载程序、能够将DOS请求转换为Windows请求的INT处理程序、能够捕获对特定内存部分的访问并将它们转换为在屏幕上绘制字符的请求的智能页面处理程序以及能够模拟应用程序使用的设备的I/O错误处理程序、为DOS编写的程序可以在Windows或Linux (DOSemu)下运行。
那么,64位呢?为了使代码能够在访问64位寄存器的情况下运行,使用了另一种保护模式,称为long mode。我对这种长模式不太了解,但据我所读,这种模式不允许处理器使用8086虚拟模式创建任务。还有另一种模式叫做兼容性模式或类似的模式,它允许处理器创建64位和32位任务,而不是8086虚拟模式任务。
如果没有CPU的帮助,DOS子系统就很难实现:您可以模拟内存映射,捕获对特定内存区域的任何访问或I/O,陷阱INT指令,但除此之外,您还应该捕获任何更新段寄存器的尝试,以便尝试模拟真正的模式寻址,而我并不确定段是否在长模式下使用。这是可行的,像DOSBox这样的应用程序证明了这一点,但是微软不再需要DOS了(它已经很长一段时间不需要它了,但是客户直到Windows2000/XP的引入才会分享他们的观点)。Windows 7 32位可以使用与以前的Windows版本相同的DOS子系统(我之前甚至读过一篇关于将OS/2子系统重新引入Windows 2000或Windows的文章),但对于Windows 7 64位,必须设计(或购买)一个全新的DOS子系统。
更多信息在这里:http://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for#Main
https://stackoverflow.com/questions/19056069
复制相似问题