我最近发现64位窗口不会运行16位应用程序(在这种情况下为.com),因为64位窗口没有16位子系统(或者互联网上说的那样)。当我尝试执行一个调用EDIT的.bat文件时,我遇到了这个。
我对x86程序集有很多经验,但从未编写程序在windows下运行(或任何其他操作系统)。由于x86系列的向后兼容性,我从来没有真正关注我的程序有多少。只要它没有使用程序必须运行的CPU中没有引入的指令,就没问题了。
我的问题是:究竟是什么使代码16,32或64位,是什么触发了16位应用程序显然存在的不兼容问题?
是否可以反汇编小型16位应用程序并稍微更改以使其正常工作,或者这是不是真的不明智?
更新:我不是在寻找一种方法来运行这些类型的应用程序,即通过模拟器或其他程序,我可以自己解决。我只是想了解使Windows接受或拒绝程序的基础机制。
答案 0 :(得分:6)
要运行“16位应用程序”(在本例中为DOS应用程序),Windows®需要在VM86模式下设置任务。问题是,当CPU处于32位VPAM(虚拟保护地址模式)时,这是有效的,这是i386操作系统使用的,但不是当CPU处于AMD引入的所谓“长模式”时。 amd64 CPU“长模式”仅支持运行32位和64位任务。
因此,64位操作系统内核无法直接在CPU上运行16位任务,您必须使用某种仿真。如果您发现可以执行此操作系统的操作系统,它可以内置该仿真,或者以32位模式而不是64位模式运行,或者在32位和64位模式下运行并在两者之间快速切换他们在某种邪恶,扭曲的黑客,我在某处读过。
根据经验,使用DOSBOX是最好的选择。
编辑:Windows®如何检测到它无法运行您的代码?
这在很大程度上取决于检测到的程序类型。它知道要处理的批处理文件(BAT
,CMD
),PIF
个文件(我认为它们仍然没有杀死它们),以及最后,COM
和EXE
可执行文件。 COM
案例很简单:65280字节 - 最大值。 16位MS-DOS®程序。另一方面,EXE
文件具有某些文件头:一个用于16位DOS(或Win3.x)部分(关键字:MZ),一个用于32位/ 64位部分(LE ,LX,PE(至少),a.out和COFF是这里的关键字,其中一些用于OS / 2兼容性或仅由它使用,一些用于各种NT变体。)
答案 1 :(得分:2)
实际上存在多个问题。首先,处理器对于每个“比特”具有不同的操作模式。但是每种类型的应用程序都需要一个超出位数的执行环境。它被称为Application Binary Interface(ABI)。例如.com文件包含需要实模式DOS环境的代码,包括某些硬件。早期版本的Windows需要启动与DosBox类似的东西才能运行它们。每种类型的可执行文件都可能不需要完整的硬件模拟,但需要大量代码才能与主操作系统进行交互。因此,对于每种类型的可执行文件,操作系统将检查所需的运行时环境类型,并拒绝运行可执行文件,除非它可以提供正确的环境。
答案 2 :(得分:1)
我的问题是:究竟是什么使代码16,32或64位,什么 显然会触发16位应用程序的不兼容问题 有?
嗯:显而易见的答案是:取决于使用8,16,32或64位寄存器的程序。显而易见但并非如此:如果处理器支持,在MS DOS中运行的程序可以使用8,16或32位寄存器。或者,Windows程序可以使用(实际上使用)8位和16位寄存器,除了使用32位寄存器和(如果处理器和OS支持它)64位寄存器。
我认为,问题应该是:究竟是什么让程序在DOS或Windows 32位或Windows 64位下运行。
首先,可执行文件的结构。 32位或64位Windows可执行文件与16位可执行文件不同。 Windows使用所谓的" Portable Executable" (PE的缩写)。 MS DOS使用.COM文件(继承自CP / M)和.EXE文件(也称为MZ可执行文件)。
第二:一个程序存储在内存中并开始执行,程序期望在那里有一些环境,例如,通过特殊指令访问的大量函数调用,如INT,负责执行不同的任务,从输出字符到控制台,打开和读取文件等等。
第三:MS DOS应用程序期望内存中的某些结构位于特定的内存地址;例如屏幕内存。此外,它还希望某些I / O设备存在于特定的I / O地址。许多所谓的“不良行为”#34;应用程序不使用BIOS或DOS在屏幕上打印,而是直接写入屏幕内存,以便更快地输出。我记得Turbo Pascal,Turbo Basic或者Turbo C编译器中的一个设置,让程序员选择控制台输出功能来通过BIOS,或者直接转到硬件。
第四:程序希望处理器以特定方式运行。 16位DOS程序旨在使用x86处理器的所谓实模式,并且此模式强加了其对内存地址的特定视野,以命名此模式的最明显特征。随着处理器处于保护模式的32位操作系统的到来,实模式程序无法工作,因为内存地址在保护模式下工作的方式与其工作方式有很大不同实模式。
愿意运行MZ可执行文件的操作系统需要某种加载器来处理这些文件(符合第一点)以及一个必须模仿应用程序应该工作的环境(遵守其余要点)。在Linux世界中,这些组件是他们所谓的个性(Linux从其他操作系统(如FreeBSD)运行代码的一种方式的一部分,前提是该代码适用于两者的同一处理器)平台)。 在Windows世界中,这称为子系统。例如,Windows XP和Windows 7具有 Win32 子系统和 DOS 子系统。古老版本的Windows(也许是Windows NT 3.5或NT 4.0)也具有 OS / 2 特性,能够运行OS / 2 16位文本模式应用程序。
因此,您的Windows操作系统需要适当的子系统来运行为MS DOS等其他操作系统设计的代码。但处理器必须以任何可能的方式提供帮助。这是因为x86平台在80386中引入了 8086虚拟模式:能够创建一个任务,其中处理器的行为与真实模式8086非常相似。
因此,在CPU本身的帮助下,适当的加载器,一个能够将DOS请求转换为Windows请求的INT处理程序,一个智能页面处理程序,能够捕获对特定内存部分的访问并将它们转换为绘制字符的请求在屏幕上,以及能够模拟应用程序以前使用的设备的I / O故障处理程序,为DOS编写的程序可以在Windows或Linux(DOSemu)下运行
那么,64位会发生什么?对于能够访问64位寄存器的代码,使用另一种保护模式,称为长模式。我对这种长模式了解不多,但从我所看到的情况来看,这种模式并不允许处理器使用8086虚拟模式创建任务。还有另一种称为兼容模式的模式或类似模式,它允许处理器创建64位和32位任务,但不能创建8086虚拟模式任务。
没有CPU辅助,DOS子系统很难实现:你可以模仿内存映射,捕获对特殊内存区域或I / O的任何访问,捕获INT指令,但此外,你应该捕获任何更新段寄存器也是为了试图模仿实模式寻址,我实际上并不确定在长模式下使用的段。它是可行的,因为像DOSBox这样的应用程序证明了它,但微软不再需要DOS(它已经很长时间不需要它了,但是客户并没有分享他们的观点,直到,或许,推出Windows 2000 / XP)。 Windows 7 32位可以使用与之前使用的Windows版本相同的DOS子系统(我甚至读过一段时间关于将OS / 2子系统带回Windows 2000或Windows XP的黑客攻击),但对于Windows 7 64位,必须设计(或购买)一个完整的新DOS子系统。
更多信息: http://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for#Main
答案 3 :(得分:0)
一般方法是使用模拟器,例如DosBox。没有办法改变二进制文件以使其使用不同的指令集运行。这必须从源代码开始。
答案 4 :(得分:0)
安装DOSBox并享受乐趣。这是免费的http://www.dosbox.com/
编辑:
代码的位数意味着有关寄存器/操作数大小的假设。另一方面,CPU的当前“位”在实模式下为16,在保护模式下,它是内存结构中的一个标志,用于描述当前正在执行的代码段(段描述符和/或页面入口) ,确切地说)。 OS设置所述存储器元数据并保持位数。根据后者,相同的命令位可能意味着
add ax, bx
或
add eax, ebx
或
add rax, rbx
CPU的位数和代码的假设更匹配。如果他们不这样做,那么在应用程序崩溃或行为异常之前不会很久。一旦代码尝试从内存中加载一个寄存器,并且CPU级寄存器大小不是代码认为的那样,CPU就会加载垃圾(或者无法加载寄存器的一部分)。试想一下32位模式下会发生什么:
MyData dw 0x17 ;2 bytes of data
SomeOtherData dw 0x200 ;2 more
...
mov ax, [MyData] ;We think we mean AX, but the CPU thinks it's EAX
EAX将加载值0x2000017。绝对不是程序所期望的。现在假设程序然后将该值与0x17进行比较,并根据该值进行条件跳转。
可以手动将16位实模式汇编转换为32位保护模式,但它不仅仅是翻译寄存器名称。从DOS程序中你必须转到Windows程序,这些是不同的。不是简单的翻译 - 更像是移植。
答案 5 :(得分:-1)
这纯粹是一个商业决策 - 根本没有技术原因,事实证明你的机器本身可以运行64位或32位版本的windows7 - 你的选择,然后你可以运行微软的XP将运行.COM
个文件的模拟器。
微软显然拥有可用的技术 - 它描述为HERE,但不允许它在Home*
版本上运行。