你为什么需要在64位系统下用32位程序
在64位系统下,用64位的程序自然是能够充分利用cpu中的64位指令和64位的地址空间,可有的时候,我们却不得不在64位系统下使用32位的程序。
64位和32位
对于64位还是32位,首先要从概念上把其理清,我觉得这可以分为三个层次:
- 硬件
主要是指CPU的指令集,寄存器,以及地址空间。比如x64体系结构的CPU,就是在32位的基础上添加了64位的操作指令,寄存器,同时提供了64位的虚拟地址空间。一台电脑能不能支持64位的系统,首先要看其硬件配置,即CPU是否支持64位指令:
比如我的Dell Inspiron 1420,用的是intel的芯片,支持EM64T指令集,是属于x64架构的。这里x64也叫x86-64,是一个体系架构,AMD的实现称为AMD64,而intel的实现称为Intel64,其指令集称为EM64T.
- 操作系统
有了64位的CPU,你才能装64位的操作系统,当然,你也完全可以在x64的机子上安装32位的系统,因为其本来就是32位cpu的一个扩展,完全支持32位指令集。
不同的64位系统有不同的编程模型(programming model),也就是常说的那些LP64, LLP64或者ILP64等等的,之所以出项这些所谓的编程模型,目的就是为了更好的兼容以前的32位下的编程模型,继而能让32位的源代码比较容易的迁移到64位(更多内容参考:64-Bit Programming Models: Why LP64?),目前Windows支持的是LLP64,而Linux/Unix支持的是LP64 - 这种编程模型的差异恐怕会给我们编写64位可移植程序带来一定的困难。
- 应用程序
有了64位的操作系统,你才能运行64位的应用程序。当然,你也完全可以在64位系统下以兼容模式运行32位程序,而且因为cpu本来就支持这些32位的指令集,所以性能基本不会有影响。
为什么需要在64位系统下使用32位程序
所以在64位的系统上,我们最好使用64位的程序,但有的情况下,我们却不得不在64位系统下运行32位程序。
原因其实很简单:不支持64位。
我们知道,一个32位的程序要移植到64位上,因为一些数据类型大小的变化(主要是指针),是需要做很多工作的,包括代码的更新与64位下的测试,所以,一些软件厂商或者开发团队会选择不支持64位,或者想支持但无法及时推出一个64位版本,这里可以分为两种情形:
- 程序
这种情况比较简单,你不支持64位,我就直接在32位兼容模式(WOW64)下跑,反正影响也不大。而且,即使你没做移植,同样可以通过重新编译而从64系统上获取一些好处:
However, on the x64 platform, 32-bit x86 applications may still benefit from a 64-bit recompile, due to the additional registers in 64-bit code, which a compiler can use for optimization.
- 库
这种情况比较复杂,一个32位的库,比如说DLL,你无法把他加载到你的64位进程中,原因很简单,类型大小不匹配。举个最简单的例子,我调用这个32位库中的函数传个指针过去,传过去的是64位的指针,可人家以为只有32位,这不撑破了吗?
要在64位的程序中使用32位的DLL,目前有个办法就是通过一个32位的进程把32位的DLL加载进来,然后通过进程间通信(RPC)。一般情况下,这个32位进程是一个进程外的COM组件(参考:Process Interoperability)。 当然,我们在设计COM接口的时候要注意32位-64位的接口兼容性。简单来讲,在Windows上采用的是LLP64模型,32位和64位的差别主要在于指针类型,因为是RPC,COM的marshalling就能很好的解决这个问题。
我想我们公司的软件Autodesk Inventor就很好的说明了这个情况,大概在07年之前,Inventor是不提供64位版本的,所以在64位系统上Inventor是以32位兼容模式运行的,原因我想应该是Inventor庞大的source code使其无法迅速移植到64位之上。这是就是第一种情况;到07年支持64位后,因为微软提供的VBA只有32位版本的(微软为了推VSTA而放弃了VBA的开发),我们只能提供一个进程外COM组件通过RPC来调用VBA,所以在64位下启动VBA速度会比较慢一点,这就是第二种情况。
当然,这些应该都是过渡期的产物,将来的趋势是要么支持64位而活下来,要么不支持64位而消亡,比如说VBA。但不可否认,这个过渡期是很漫长的。