1.Common Visual C++ 64-bit Migration Issues
When you use Visual C++ to create applications to run on a 64-bit Windows operating system, you should be aware of the following issues:
当你用Visual c++创建运行在64位Windows上的程序时,你应该意识到下列问题:
-
An
int
and along
are 32-bit values on 64-bit Windows operating systems. For programs that you plan to compile for 64-bit platforms, you should be careful not to assign pointers to 32-bit variables. Pointers are 64-bit on 64-bit platforms, and you will truncate the pointer value if you assign it to a 32-bit variable.
在64位系统上int型和long型占32位(IL32)。当你在64位平台上编译程序时,你需要注意不要把指针赋值给32位变量。在64位系统上,指针占64位(P64),当你将它赋值给32位变量时,会发生指针值截断(高位截断)。
-
size_t
,time_t
, andptrdiff_t
are 64-bit values on 64-bit Windows operating systems.
size_t,time_t和ptrdiff_t在64位系统上占64位
-
time_t
is a 32-bit value on 32-bit Windows operating systems in Visual C++ versions before Visual C++ 2005.time_t
is now a 64-bit integer by default. For more information, see Time Management.
Visual c++ 2005之前的Visual c++版本,time_t占32位在32位系统上。现在time_t默认是64位整型。(为了处理32位时间漏洞?)
You should be aware of where your code takes an int
value and processes it as a size_t
or time_t
value. It is possible that the number could grow to be larger than a 32-bit number and data will be truncated when it is passed back to the int
storage.
你应该意识到,当你的代码中将int型变量赋值给size_t或者time_t型变量,那么数值可能会超过32位,当你再把size_t或者time_t变量赋值给int型,有可能会发生数据截断。
The %x (hex int
format) printf
modifier will not work as expected on a 64-bit Windows operating system. It will only operate on the first 32 bits of the value that is passed to it.
printf中的%x占位符在64位系统上不会按所预期的来运行。它仅对传递给它的前32位值进行操作。
-
Use %I32x to display a 32-bit integral type in hex format.
(在64位系统上)用%I32x显示32位整型类型的16进制格式
-
Use %I64x to display a 64-bit integral type in hex format.
(在64位系统上)用%I64x显示64位整型类型的16进制格式
-
The %p (hex format for a pointer) will work as expected on a 64-bit Windows operating system.
%p(显示指针16进制格式)在64位系统上运行的结果符合预期
2.x64 software conventions [节选]
Overview of x64 calling conventions
x64位调用约定概述
Two important differences between x86 and x64 are the 64-bit addressing capability and a flat set of 16 64-bit registers for general use. Given the expanded register set, x64 uses the __fastcall calling convention and a RISC-based exception-handling model. The __fastcall
convention uses registers for the first four arguments and the stack frame to pass additional arguments. For details on the x64 calling convention, including register usage, stack parameters, return values, and stack unwinding, see x64 calling convention.
x86和x64系统存在两个重要的不同:64位寻址能力和平坦的16个64位通用寄存器组。采用扩展寄存器组后,x64(架构)使用__fastcall调用约定以及基于RISC(精简指令集)的异常处理模型。__fastcall调用约定使用通用寄存器传递前4个参数,用堆栈传递其余的参数。
Register usage
寄存器的使用
The x64 architecture provides for 16 general-purpose registers (hereafter referred to as integer registers) as well as 16 XMM/YMM registers available for floating-point use. Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used.
x64架构提供了16个通用寄存器(以下简称整数寄存器)和16个XMM/YMM浮点寄存器。易失型寄存器是指调用方假设在调用过程中寄存器值会发生变化的暂存型寄存器。非易失型寄存器是指调用过程中寄存器值由被调用方负责保存并恢复。
Register volatility and preservation
寄存器的易失性和保存方式
The following table describes how each register is used across function calls:
下表描述了各个寄存器在函数调用过程中的用途:
Register | Status | Use |
RAX | Volatile | Return value register |
RCX | Volatile | First integer argument |
RDX | Volatile | Second integer argument |
R8 | Volatile | Third integer argument |
R9 | Volatile | Fourth integer argument |
R10:R11 | Volatile | Must be preserved as needed by caller; used in syscall/sysret instructions |
R12:R15 | Nonvolatile | Must be preserved by callee |
RDI | Nonvolatile | Must be preserved by callee |
RSI | Nonvolatile | Must be preserved by callee |
RBX | Nonvolatile | Must be preserved by callee |
RBP | Nonvolatile | May be used as a frame pointer; must be preserved by callee |
RSP | Nonvolatile | Stack pointer |
XMM0, YMM0 | Volatile | First FP argument; first vector-type argument when __vectorcall is used |
XMM1, YMM1 | Volatile | Second FP argument; second vector-type argument when __vectorcall is used |
XMM2, YMM2 | Volatile | Third FP argument; third vector-type argument when __vectorcall is used |
XMM3, YMM3 | Volatile | Fourth FP argument; fourth vector-type argument when __vectorcall is used |
XMM4, YMM4 | Volatile | Must be preserved as needed by caller; fifth vector-type argument when __vectorcall is used |
XMM5, YMM5 | Volatile | Must be preserved as needed by caller; sixth vector-type argument when __vectorcall is used |
XMM6:XMM15, YMM6:YMM15 | Nonvolatile (XMM), Volatile (upper half of YMM) | Must be preserved by callee. YMM registers must be preserved as needed by caller. |
On function exit and on function entry to C Runtime Library calls and Windows system calls, the direction flag in the CPU flags register is expected to be cleared.
当进入和退出C运行库函数和Windows系统调用,CPU标志寄存器(x86中的eflags寄存器)的方向位将被清除。
Image format
可执行映像文件的文件格式
The x64 executable image format is PE32+. Executable images (both DLLs and EXEs) are restricted to a maximum size of 2 gigabytes, so relative addressing with a 32-bit displacement can be used to address static image data. This data includes the import address table, string constants, static global data, and so on.
x64位可执行程序的文件格式是PE32+。可执行程序(DLLs和EXEs)大小被限制为2GB,所以,可以使用32位位移的相对寻址方式来处理静态数据,如:IAT表,字符串常量,静态全局数据(全局变量?)等等