设为首页 收藏本站
查看: 627|回复: 0

[经验分享] 将程序移植到64位Windows

[复制链接]

尚未签到

发表于 2016-5-21 02:14:38 | 显示全部楼层 |阅读模式

  雷立辉整理
  简介:本文对如何将32位Windows程序平滑的支持和过渡到64位Windows操作系统做出了一个简单而系统的介绍。包括对于64位操作系统的版本,编程模型,一些移植原则甚至包括对驱动程序的移植原则的介绍。
  作者介绍:系统分析员,现在在北京工作。作者的blog:http://goooder.blogchina.com.
前言:
  或许大家还对32位的CPU及操作系统使用还是觉得非常的合乎日常需要,但Windows 64位已经悄悄的来到了各位的身边。不少软件厂商也纷纷宣称自己的软件已经支持64位操作系统了。
  笔者在几个月之前就成功的实施了一个软件的64位操作系统移植。大致方案是,上层应用程序仍然使用32位程序,但将该系统软件的驱动程序统统的变成了64位。这也是让应用程序支持64位的最小代价。整个过程前后不到一个月(两个人月),就解决了大部分问题。而一些难啃的骨头都是因为以前的编码不太规范而引起的。因为这不是本文的主题,所以就此打住。
  下面的内容就是我在工作过程中整理各种资料所得到的成果。为了文章的系统性,中间转贴了一些MSDN中文网站的内容。希望能对大家的工作有所帮助。
一.最有可能受益于64位的应用
  l需要大量的可寻址内存,因而系统总体内存需求超过4GB的应用。例如那些采用大型数据集的应用(金融和科学建模软件)和基于主机的桌面应用(在不降低性能的情况下同时运行多个线程);
  l必须同时管理大量的用户或者应用线程,例如大规模的瘦客户端解决方案,大型数据库,以及用于客户关系管理(CRM)、供应链管理(SCM)、企业资源规划(ERP)和数字版权管理(DRM)系统中的解决方案的数据仓库应用;
  l需要通过实时加密和解密提高安全性的应用,包括电子商务应用和对专用或者分类数据的保护;
  l需要数学精度和浮点性能的应用,包括建模、模拟、统计和金融分析、图像/视频/信号处理、物理、医学研究、远程通信、加密和压缩;
  l需要大规模的、强大的数据库性能的应用,包括决策支持,搜索和索引,文档和内容管理,以及语音识别;
  l需要64位计算的大内存寻址功能的应用,包括很多高性能计算(HPC)群集应用;
  l需要提供数字内容创建功能,例如计算机辅助设计、制造和工程(CAD、CAM和CAE)、数字音乐制作和视频编辑,以及实时媒体流解决方案;
  l需要通过最大限度的性能实现逼真的影院级消费者体验,包括计算机游戏、数字视频和协作;
  l需要将以前只限于64位工作站的功能移植到企业、消费者和计算机爱好者的台式机中,包括3D建模、渲染、动画、模拟和软件开发。
二.Windows XP的64位版分类
  微软在2003年3月28日发布了64位的Windows XP。64位的Windows XP称Windows XP 64-Bit Edition。其实就是64位版本的Windows XP Professional。根据不同的微处理器架构,它分为两个不同版本:
1.IA-64版的Windows XP
  针对英特尔(Intel)的IA-64架构的安腾2(Itanium2)纯64位微处理器的Windows XP 64-Bit Edition Version 2003 for Itanium-based Systems。它是拥有64位寻址能力的强大的操作系统,主要面向顶级的高端IA-64架构的工作站,用在高端的科学运算,石油探测工艺,立体绘图,复杂的动画制作等等,是一种用在高效能运算(High Performance Computing)的强大的操作系统。估计它可能会改名为Windows XP Professional Itanium-based Edition。支持双处理器;最低支持1GB的内存,最高支持16GB的内存。
2.x64版的Windows XP
  针对超微(AMD)的x64架构的皓龙(Opteron)与速龙64(Athlon64)所属的64位扩展微处理器的Windows XP 64-Bit Edition for 64-Bit Extended Systems。由于英特尔也发布了x64架构的Intel EM64T技术的至强(Xeon)与奔腾4(Pentium 4)的64位扩展微处理器,故微软将该版本的的Windows XP 64-Bit Edition改为Windows XP Professional x64 Edition,它支持AMD与Intel的x64架构。可以使用在一般x64架构的工作站,桌面电脑以及笔记本电脑,用途与32位Windows XP Professional一样,但具有64位寻址能力。支持双处理器;最低支持256MB的内存,最高支持16GB的内存。
  <shapetype id="_x0000_t75" coordsize="21600,21600" path=" m@4@5 l@4@11@9@11@9@5 xe" filled="f" stroked="f"><stroke joinstyle="miter"><formulas><f eqn="if lineDrawn pixelLineWidth 0 "><f eqn="sum @0 1 0 "><f eqn="sum 0 0 @1 "><f eqn="prod @2 1 2 "><f eqn="prod @3 21600 pixelWidth "><f eqn="prod @3 21600 pixelHeight "><f eqn="sum @0 0 1 "><f eqn="prod @6 1 2 " style="font-weight: normal;"><f eqn="prod @7 21600 pixelWidth "></f></f></f></f></f></f></f></f></f></formulas></stroke></shapetype>
  http://goooder.blogchina.com/inc/image00133.jpg
  Windows XP Professional x64 Edition与32位版本很相像
三.x64版的Windows操作系统的设计目标
  x64版有5大特征,即:
  1.同时轻松支持32位Win32程序及64位程序;
  2.在64位运行的程序代码和32位运行的程序应该是同一份代码;
  3.使现有程序具有企业级应用性能;(Enable existing applications to scale to enterprise capacities)
  4.支持新的设计使之可以利用巨大地址空间及内存空间;
  5.支持32位既有程序。
  x64位平台并没有出现Win64 API,它仍然是熟悉的Win32 API(现在更合适的名称为Windows API)。但它出现了一些新的兼容64位的数据类型,所以可能需要对代码进行少量的更改。这就意味着开发者可以从单个代码库构建代码的32位和64位版本,减少了由于维护两个代码库所带来的维护开销。
  但是,在x64中,Microsoft已经去除了一些旧的组件,如Win16子系统。所以Windows 64位代码不支持16位的Windows程序。也不支持POSIX和OS/2子系统。又出现了一个新的子系统,称为WOW64。
四.x64新出现的子系统―WOW64
  WOW64是Windows-32-on-Windows-64的缩写。它为现有的32位应用程序提供了32位的模拟环境,可以使大多数32位应用程序在无需修改而直接运行在Windows 64位版本上。它类似于旧的WOW32子系统,负责在Windows 32位版本下运行16位的代码。
  http://goooder.blogchina.com/inc/image00442.gif
  尽管x64 CPU本身具有32位兼容性模式,可以处理IA-32指令的实际执行,但WOW层仍然必不可少。WOW子系统负责诸如在32位和64位模式之间进程切换以及模拟32位系统的服务。例如,32位和64位程序具有不同的注册表配置单元,还有一个用于32位二进制文件的不同的系统目录,而且64位二进制文件仍然使用System32目录。因此,当32位应用程序安装到系统中时,WOW层会确保将32位二进制文件置于一个新的目录SysWOW64中。这是通过如下方式实现的:根据应用程序是否运行在WOW下,截获对API的调用(如GetSystemDirectory)并返回适当的目录。类似的问题可能会存在于注册表中。因为32位和64位的COM服务器都可以安装在系统上,并位于相同的类标识符(CLSID)下,因此WOW层需要将对注册表的调用重定向到适当的32位或64位配置单元中。WOW层也会处理注册表中某些区域之间的镜像更改,以便使其更简单地支持32位和64位代码之间的交互操作。
  WOW64非常重要,因为当不关注性能和可伸缩性的问题时,它使开发者可以利用大多数现有的32位代码。它是两种方法的最佳结合。开发者可以将应用程序服务迁移到64位,同时将Microsoft管理控制台(MMC)配置管理单元保留为32位。Windows 64位版本包括MMC的32位和64位的版本。当选择保留管理工具为32位时,进程间的通讯可能会遇到某些问题,但是只要接口设计正确,诸如远程过程调用(RPC)的协议应该可以在32位和64位进程之间运行。有关WOW64的另外一点需要牢记:它并不是为要求高性能的应用程序而设计的。至少,WOW64子系统需要将32位参数扩展到64位,并且需要将64位的返回值截断为32位。在最糟糕的情况下,WOW64子系统将需要进行内核调用,涉及到的不仅仅是到内核的转换,还有从处理器的32位兼容性模式到其本机64位模式的转换。在WOW64下运行时,应用程序将无法妥当地进行调整。对于那些要将其保留为32位的应用程序而言,必须在WOW64下测试它们。如果性能不能满足期望,则需要考虑将应用程序迁移到64位。
  WOW64是在用户模式下实现的,作为ntdll.dll和内核之间的层。WOW64及其支持的一些DLL仅仅是可以加载到32位进程中的64位的DLL。对于所有其他情况,进程保持为纯进程。32位的进程无法加载64位的DLL,反之亦然。所以,请检查代码中的所有“LoadLibrary”调用是否有效。
  有关WOW64的详细信息,请参阅Microsoft_ Platform SDK中的“64-bit Windows Programming - Running 32-bit Applications”。
五.64位windows内存地址空间映射
  默认情况下,Windows 32位版本的地址空间限制在4GB,其中一半是为内核保留的。这限制了普通的应用程序只能使用2GB的有效虚拟内存。2 GB看起来好像很多,但是由于错误的分配算法、大型文件映射甚至过多的使用DLL,地址空间很容易在应用程序中变得零碎。看一下任务管理器中的“VM Size”列,就会发现普通应用程序消耗的虚拟内存量。当然,就想过去的DOS时期(利用XMS/EMS)一样,有很多种方法可以使32位的应用程序访问多于4 GB的物理内存。进入物理地址扩展(PAE)和地址窗口扩展(Address Windowing Extensions,AWE)。PAE通过将地址位的数量从32扩展到36来工作,这样使应用程序可以寻址的空间达到64 GB。AWE使应用程序可以将大于4 GB的物理内存范围映射到虚拟地址空间中。这两种方法都引入了开销并增加了代码的复杂性。
  Windows 64位版本提供16 TB的有效寻址空间,其中一半可用于用户模式的应用程序。这意味着整个数据库可以移动到内存中,显著地提高了性能,或者整个网站可以缓存到内存中。它还可以使代码保留并委托到巨型的邻近虚拟内存块中,无需实际地担心虚拟内存碎片问题。这也考虑到了巨型文件映射对象或共享的内存部分。
  下面是64位体系结构和32位体系结构的比较表格:
  
  地址空间
  64位Windows
  32位Windows
  虚拟内存
  16 TB
  4 GB
  页面文件
  512 TB
  16 TB
  页面缓冲池
  128 GB
  470 MB
  非页面缓冲池
  128 GB
  256 MB
  系统缓存
  1 TB
  1 GB
  下面是Windows系列内存地址空间分配比较:http://goooder.blogchina.com/inc/image004323.jpg

六.Windows 64位版本的C/C++编程
1.64位编码指导原则
  Windows 64位版本使用LLP64数据模型。这意味着标准C类型int和long保持为32位整数。数据类型size_t将映射到处理器词大小(IA32为32位,IA64为64位),并且__int64是64位整数。在协助迁移32位代码时就会完成上述操作。意义在于您可以对应用程序的32位版本和64版本使用相同的代码库。
  还有一个称为LP64的数据模型,它将标准的C类型long映射到64位整数,并使int保持为32位的整数。这种数据模型常见于Unix平台,但从单个代码库同时创建应用程序的32位和64位版本时可能有一些困难。您可能注意到了此处的常见主题。32位平台与64位平台的思想就是应该能够从单个代码库中构建两个版本的应用程序。如果无法做到,那么您可能要重新审视您的设计。具有单个代码库就是巨大的胜利,尤其是如果您计划发行两个版本。
  综合以上考虑,建议如下:
  l使用Windows64位或32位安全数据类型;
  l检查所有的指针运算及使用指针的地方;
  <span lang="EN-US" l改写所有嵌入的汇编代码;使用intrinsics或者native assembly code;
  l对于X64相关代码使用#if defined (_AMD64__)的预编译命令(没有定义__IA64__宏);
  l对于IA64相关的代码使用#if defined (__IA64__)命令;
  l编译x64程序使用AMD64处理器;
  用Visual C++创建在64位Windows操作系统中运行的应用程序时,应注意以下问题:
  l在64位Windows操作系统中,int和long是32位值。
  l在64位Windows操作系统中,size_t、time_t和ptrdiff_t是64位值。
  l在32位Windows操作系统中,time_t是32位值。
  l应注意代码在哪里采用int值和将其作为size_t值或time_t值处理。数字有可能增长得比32位数大,并且数据在被传递回int存储时有可能被截断。
  l%x(十六进制int格式)printf修饰符在64位Windows操作系统中不按预期的那样工作;它只对传递给它的值的前32位进行操作。
  lWindows 32位操作系统使用%I32x显示整数。
  <span lang="EN-US" lWindows 64位操作系统使用%I64x显示整数。
  l%p(指针的十六进制格式)在64位Windows操作系统中按预期的那样工作。
2./WP64:使编译器警告您潜在的问题
  Microsoft_ Visual C和Microsoft_ Visual C++_ .NET 2002编译器添加了/WP64开关,这使您可以测试32位代码的64位兼容性问题。编译器将发出有关指针截断和不正确转换的警告。将32位应用程序迁移到Windows 64位版本中前面的一个步骤就是打开这个标记,然后就像通常编译代码那样来编译您的代码。第一次会有几个错误。例如,请看下面这个代码片段:
  DWORDi= 0;
  size_tx = 100;
  i= x; // C4267: warning C4267: '=' : conversion from
  // 'size_t' to 'DWORD', possible loss of data.
  在32位的平台上,这段代码能够很好的进行编译,因为size_t是32位的,但是在64位的平台上,size_t就是64位的整数。启用/WP64后,编译器将会警告您类似的情况。
  其他示例:
  voidfunc(DWORD context)
  {
  char*sz= (char*)context; // C4312: warning C4312:
  // 'type cast' : conversion
  // from 'DWORD' to 'char *' of
  // greater size
  // Do something withsz..
  }
  char* string = "the quick brown fox jumped over the lazy dog.";
  func((DWORD)string); // C4311: warning C4311: 'type cast' :
  // pointer truncation from 'char *'
  // to 'DWORD'
  在修复这些错误后,请测试您的32<san>位代码。您希望确保32位的代码继续按预期那样工作。32位和64位二进制文件应该从相同的代码库中构建。这就是编写不断前进的Windows应用程序的关键概念。开始时,您需要考虑32位和64位的问题,并且为应用程序编写可以运行在这两个平台上的代码。</san>
3.多态类型
  由于Win32 API是针对C的,在很多情况下,您都需要将整数转换成指针或者相反。在32位的硬件上不会有问题,其中指针的大小和整数的大小是相同的,但在64位的硬件上却完全不一样。这就是多态类型出现的原因。
  对于特定的精度,您可以使用固定精度的数据类型。不管处理器的词大小如何,它们的大小都是一致的。大多数这些类型都在它们的名称中包含精度,可以从下面的表中看出:
  表1.固定精度的数据类型
  类型
  定义
  DWORD32
  32位无符号整数
  DWORD64
  64位无符号整数
  INT32
  32位有符号整数
  INT64
  64位有符号整数
  LONG32
  32位有符号整数
  LONG64
  64位有符号整数
  UINT32
  无符号INT32
  UINT64
  无符号INT64
  ULONG32
  无符号LONG32
  ULONG64
  无符号LONG64
  此外,当您需要数据类型的精度随着处理器词大小变化时,请使用指针精度数据类型。这些类型又称为“多态”数据类型。这些类型通常以_PTR后缀结尾,如下面的表格所示:
  表2.指针精度的数据类型
  类型
  定义
  DWORD_PTR
  指针精度的无符号长类型
  HALF_PTR
  指针大小的一半。用于包含一个指针和两个小型字段的结构中
  INT_PTR
  指针精度的有符号整型
  LONG_PTR
  指针精度的有符号长类型
  SIZE_T
  指针可以引用的最大字节数。用于必须跨指针的整个范围的计数
  SSIZE_T
  有符号SIZE_T
  UHALF_PTR
  无符号HALF_PTR
  UINT_PTR
  无符号INT_PTR
  ULONG_PTR
  无符号LONG_PTR
  LPARAM
  与LONG_PTR为同义词,(在WTypes.h中定义)
  WPARAM
  与UINT_PTR为同义词,(在WTypes.h中定义)
  通过整数参数传递参数或上下文信息的所有Win32 API都更改为使用这些新的类型。SetWindowLong和SetWindowLongPtr函数都是很好的示例:
  旧方法:
  LONGSetWindowLong(
  HWNDhWnd,
  intnIndex,
  LONGdwNewLong);
  新的多态方法:
  LONG_PTRSetWindowLongPtr(
  HWNDhWnd,
  intnIndex,
  LONG_PTRdwNewLong);
  请注意,该函数的xxxPtr版本使用新的多态类型。对于开发人员而言,通过在窗口的额外数据区域中存储指针来存储窗口的上下文信息是相当常见的。使用SetWindowLong函数在Windows 32位版本上存储指针的任何代码必须更改为调用SetWindowLongPtr。该更改非常简单并且很快就可以完成,因为大多数更改要求使用多态类型。
  另外,WindowProc和GetQueuedCompletionStatus也是很好的示例:
  LRESULT CALLBACKWindowProc(
  HWNDhWnd,
  UINTuiMsg,
  WPARAMwParam,
  LPARAMlParam);
  BOOLGetQueuedCompletionStatus(
  HANDLEhCompletionPort,
  LPDWORDlpNumberOfBytes,
  PULONG_PTRlpCompletionKey,
  LPOVERLAPPED*lpOverlapped,
  DWORDdwMilliseconds);
  WindowProc使用LPARAM,后者是多态类型。GetQueuedCompletionStatus使用ULONG_PTR,后者也是多态类型。这使那些假设整数的大小与指针大小相同的现有代码可以在进行很少修改的情况下继续工作。
  Microsoft_ Visual Studio_ .NET 2002的编译器包含两个新的优化模式:Link Time Code Generation(LTCG,又称Whole Program Optimization)和Profile Guided Optimization (PoGO)。代码优化在Itanium处理器上比在x86平台上更为重要,因为编译器对生产高效代码负有全部责任。对于编译器方面的知识,请参考MSDN中文网站http://www.microsoft.com/china/MSDN/library/windev/Windows2003/NFdnnetservws0364bitdev.mspx来获得更多此方面的内容。
七.将驱动移植到64位Windows操作系统
  x64位操作系统和x32位操作系统的最大区别就是内存寻址方式的不同。而64位操作系统不支持32位的驱动程序,因为驱动程序和windows内核同处于一个地址空间中。这是移植32位驱动到64位驱动的最大原因。当然,64位驱动程序可以使用更大的分页内存,非分页内存及系统缓存。而且,你的设备从此就支持64位windows操作系统了。
1.在X64下的驱动程序安装
  除了要把应用程序的32位驱动程序变成64<spn>位程序之外,驱动的安装程序和其它配置文件同样需要修改。也就是说,对于要在x64上运行的32位程序,它所依赖的驱动仍然需要是64位的。这些相关程序包括inf文件,device installers, class installers和co-installers。相关资料可查看MSDNLibararyDDK:<a href="http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/Other_394c38ae-a3e6-45fb-87f2-c3e227cb6b7c.xml.asp">Porting Your Driver to 64-Bit Windows</a>。</spn>
  所以,要改造应用程序的安装程序。方法是,让32位版的驱动安装为缺省安装选项,即用户插入安装光盘之后,依然运行32位安装程序。但当程序调用UpdateDriverForPlugAndPlayDevices返回值为ERROR_IN_WOW64时,这说明该安装程序正运行在64位Windows环境中。此时,这个安装程序应该调用CreateProcess函数来启动64位的安装进程。这个64位的安装进程通过调用64位驱动目录下的inf文件进行驱动安装。
2.驱动要支持32位IOCTL
某些IOCTL可能包含含有指针的结构,所以,要特别小心的区别对待它,必须根据被调用者解析结构或者输出结构。
  有三种办法可以解决这个问题:
  1.尽量避免使用IOCTL传递包含有指针的结构;
  2.通过API IoIs32bitProcess()来判断上层调用者的程序类型;
  3.在64位程序中采用新的IOCTL命令;
  例子:
  IOCTL structure in header file
  typedefstruct_IOCTL_PARAMETERS {
  PVOIDAddr;
  SIZE_T Length;
  HANDLEHandle;
  } IOCTL_PARAMETERS, *PIOCTL_PARAMETERS;
  32-bit IOCTL structure
  //
  // This structure is defined
  // inside the driver source code
  //
  typedefstruct_IOCTL_PARAMETERS_32 {
  VOID*POINTER_32Addr;
  INT32 Length;
  VOID*POINTER_32 Handle;
  } IOCTL_PARAMETERS_32, *PIOCTL_PARAMETERS_32;
  32-Bit and 64-Bit IOCTL
  #ifdef_WIN64
  case IOCTL_REGISTER:
  if (IoIs32bitProcess(Irp)) {
/* If this is a 32 bit process */
params32 = (PIOCTL_PARAMETERS_32)(Irp>AssociatedIrp.SystemBuffer);
  if(irpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof(IOCTL_PARAMETERS_32)) {
  status = STATUS_INVALID_PARAMETER;
  } else {
LocalParam.Addr= params32->Addr;
LocalParam.Handle= params32->Handle;
LocalParam.Length= params32->Length;
  /* Handle theioctlhere */
  status = STATUS_SUCCESS;
Irp->IoStatus.Information=sizeof(IOCTL_PARAMETERS);
}
} else { /* 64bit process IOCTL */
  } else { /* 64bit process IOCTL */
  params= (PIOCTL_PARAMETERS)
(Irp->AssociatedIrp.SystemBuffer);
  if (irpSp->Parameters.DeviceIoControl.InputBufferLength
<sizeof(IOCTL_PARAMETERS)) {
status = STATUS_INVALID_PARAMETER;
  } else {
RtlCopyMemory(&LocalParam,params,
sizeof(IOCTL_PARAMETERS));
  /* Handle theioctlhere */
status = STATUS_SUCCESS;
}
Irp->IoStatus.Information=sizeof(IOCTL_PARAMETERS);
}
break;
3.64-Bit INF文件要求
  在Windows Server 2003SP1之后,64位驱动的安装被提高了要求。这可以简化用户的操作及提高安全性。
  Inf文件中必须含有NTAmd64或者NTIA64之类的修饰符才行。具体做法是在[Manufacturer]和Models小节都需要添加此类的字段。
  [Manufacturer]
  %mycompany% =MyCompanyModels
  [MyCompanyModels]
  %MyDev% =mydevInstall,mydevHwid
  [Manufacturer]
  %mycompany% = MyCompanyModels,NTx86,NTAmd64
  [MyCompanyModels.NTx86]
  %MyDev% = mydevInstallx86,mydevHwid
  [MyCompanyModels. NTAmd64]
  %MyDev% = mydevInstallAmd64,mydevHwid
  如果只需要在WindowsX64系统上安装,则只需要使用NTAmd64修饰符就可以了。更多请参考http://www.microsoft.com/whdc/driver/install/64INF_reqs.mspx。
4.编程中容易碰到的问题
1)指针的相关问题
  如果原有项目的编程风格控制不严,指针类型混用,强制转换使用过多等等可能对移植是一个巨大的考验。另外,程序中存在结构之中根据具体数据类型来计算其它变量的位置此类的代码也需要重新检查。
  使用指针的原则如下:
  1.不要将指针强制转换为int, long, ULONG, DWORD等类型,而应该使用UINT_PTR和INT_PTR;
  2.使用PtrToUlong()和PtrToLong()来截断指针;
  3.永远不要将已经截断的存贮在int或者ULONG中指针地址的重新合成一个新的指针地址;
  4.小心的计算缓冲区的大小,说不定缓冲区的长度比ULONG所能存储的最大数都大!
  5.小心的调用那些传出指针的函数;
  对4可以举个例子:比如说有两个地址ptr2(高地址), ptr1(低地址),则len= ptr2 – ptr1将有可能大于2的32次方。
2)结构的内存排列问题
  在64位的操作系统上,结构的内存排列(structure alignment)也需要小心审查。内存排列的齐整有利于处理器的执行效率。如果打开了一些编译选项,为了对齐内存地址,编译器可能会将某些位置填空。在移植过程中,对结构中的变量顺序需要仔细检查,特别是在同一个头文件中使用不同的pack选项。比如下面的代码:
  #pragmapack (1) /*也可以使用编译选项/Zp(结构成员对齐)*/
  structAlignSample{
  ULONG size;
  void *ptr;
  };
  structAlignSamples;
  voidfoo(void *p) {
  *p = p; //将会导致访问异常
  ...
  }
  foo((PVOID)&s.ptr);
  补救办法就是使用宏UNALIGNED:
  voidfoo(void *p) {
  structAlignSamples;
  *(UNALIGNED void *)&s.ptr= p;
  }
  当然,更好的办法就是首先将那些64位长度的数据类型变量放在结构的前端。
3)小心使用十六进制的常量,无符号整数
  小心使用十六进制的常量,无符号整数等等。比如说下面的一些断言在64位系统中是错误的:
  ~((UINT64)(PAGE_SIZE-1)) == (UINT64)~(PAGE_SIZE-1)
  PAGE_SIZE = 0x1000UL // Unsigned Long - 32 bits
  PAGE_SIZE - 1 = 0x00000fff
  等式左边:
  //无符号转换
  (UINT64)(PAGE_SIZE -1 ) = 0x0000000000000fff
  ~((UINT64)(PAGE_SIZE -1 ))= 0xfffffffffffff000
  等式右边:
  ~(PAGE_SIZE-1) = 0xfffff000
(UINT64)(~(PAGE_SIZE-1))=0x00000000fffff000
  所以:
  ~((UINT64)(PAGE_SIZE-1))!= (UINT64)(~(PAGE_SIZE-1))
  还有:
  DWORD index = 0;
  CHAR *p;
  If (p[index – 1] == ‘0’)
  上面的代码将会在64位系统上出错!因为在32位系统上
  p[index-1] == p[0xffffffff] == p[-1]
  这是对的。但在64位系统上:
  p[index-1] == p[0x00000000ffffffff] != p[-1]
  再如:
  -1 != 0xFFFFFFFF
  0xFFFFFFFF != invalid handle
  DWORD总是32位,所以要查找原有程序中所有用DWORD存贮指针的代码。另外,别忘了使用%I来打印指针地址,而且大于0x80000000的也未必是内核态地址了。
5.开发64位驱动的工具
  64位的开发工具和32位的差不多,除了必须的Windows DDK 2003之外,Windbg,Driver Verifier等都是拿手的好工具。最后,下载一份最新的WHQL测试包进行WHQL测试也是值得推荐的。
  目前,学会使用Windbg来调试64位用户态和核心态程序的方法是尤为必要的。也可以购买支持64位的VC环境VisualStdio2005来进行64位程序开发。
参考资料
  Windows XP Professional x64 Edition概述http://www.microsoft.com/china/windowsxp/64bit/evaluation/overviews/overview.mspx
  AMD64计算平台-带您进入计算的未来白皮书http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/Other_f910e5d8-a732-4faa-a8d2-d4de021dc78d.xml.asp
  64-bit DDK编程指导
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/Other_f910e5d8-a732-4faa-a8d2-d4de021dc78d.xml.asp
  硬件测试资料
http://www.microsoft.com/whdc/system/platform/64bit/default.mspx
  http://goooder.bokee.com/2000408.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-219620-1-1.html 上篇帖子: WINDOWS专集大集合,绝对是精品中的精品 下篇帖子: Microsoft Windows "keybd_event" Local Privilege Escalation Exploit
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表