我刚刚收到了一个错误报告,称在“64位机器”上运行程序时才会出现问题。 现在,Delphi不生成64位代码,所以理论上这不应该有影响,但显然在这种情况下确实有影响。 我想我有一种解决方法,但这将破坏在32位Windows上的东西,因此我需要一些方式来判断:
- 如果我正在运行x64或x86处理器
- 如果我正在运行在Win32仿真或本地Win32上的64位Windows版本或32位操作系统上的本机Win32。
有人知道如何从我的应用程序中获取这些答案吗?
Mason,你可以使用IsWow64Process函数(WOW64是x86模拟器,允许32位基于Windows的应用程序在64位Windows上无缝运行)。
Uses Windows;
type
WinIsWow64 = function( Handle: THandle; var Iret: BOOL ): Windows.BOOL; stdcall;
function IAmIn64Bits: Boolean;
var
HandleTo64BitsProcess: WinIsWow64;
Iret : Windows.BOOL;
begin
Result := False;
HandleTo64BitsProcess := GetProcAddress(GetModuleHandle('kernel32.dll'), 'IsWow64Process');
if Assigned(HandleTo64BitsProcess) then
begin
if not HandleTo64BitsProcess(GetCurrentProcess, Iret) then
Raise Exception.Create('Invalid handle');
Result := Iret;
end;
end;
再见。
我看到你的第二个问题(你是否在Win64上运行?)已经得到了回答。请记住,为了使您的代码具有未来性,您需要考虑在Win64上运行的(假设的)64位Delphi应用程序中,IsWow64Process也将返回FALSE。
关于您的第一个问题 - 你是否在64位CPU上 - 你可以检查硬件是否具有相应的CPUID功能标志,如下面的代码所示。
function Is64BitProcessor: boolean;
begin
Result:=false;
if CpuidAvailable = true then Result := Has64BitFeatureFlag;
end;
此处使用以下两个低级函数:
function CPUIDavailable:boolean;
asm // if EFLAGS bit 21 can be modified then CPUID is available
pushfd //Save Flags
pushfd //Copy flags to EAX
pop eax
mov ecx,eax //Make another copy in ECX
btc eax,21 //Complement bit 21
push eax //Copy EAX to flags
popfd
pushfd //Copy flags back to EAX
pop eax
cmp eax,ecx //Compare "old" flags value with potentially modified "new" value
setne al //Set return value
popfd //Restore flags
end;
function Has64BitFeatureFlag: boolean; asm //如果CPUID.80000001h.EDX[bit29] = 1,则表示该处理器支持64位。 //但首先需要检查是否存在函数80000001h。 push ebx //由于CPUID将改变EBX,因此保存EBX push esi //我们将在内部使用ESI,因此保存ESI
xor eax,eax //Setting EAX = input param for CPUID to 0
cpuid //Call CPUID.0
//Returns -> EAX = max "standard" EAX input value
mov esi, eax //Saving MaxStdInput Value
mov eax,80000000h //Setting EAX = input param for CPUID to $80000000
cpuid //Call CPUID.80000000h
//Returns -> EAX = max "extended" EAX input value
//If 80000000h call is unsupported (no 64-bit processor),
//cpuid should return the same as in call 0
cmp eax, esi
je @No64BitProcessor //IF EAX{MaxExtInput} = ESI{MaxStdInput} THEN goto No64BitProcessor;
cmp eax, 80000001h
jb @No64BitProcessor //IF EAX{MaxExtInput} < $80000001 THEN goto No64BitProcessor;
mov eax,80000001h //Call $80000001 is supported, setting EAX:=$80000001
cpuid //Call CPUID.80000001h
//Checking "AMD long mode"/"Intel EM64T" feature bit (i.e., 64bit processor)
bt edx, 29 //by checking CPUID.80000001h.EDX[bit29]
setc al //IF Bit29=1 then AL{Result}:=1{true; it's a 64-bit processor}
jmp @Exit //Exit {Note that Delphi may actually recode this as POP ESI; POP EBX; RET}
@No64BitProcessor: xor eax, eax //结果{AL/EAX}:=0{假; 这是一个32位处理器}; @Exit: pop esi //恢复ESI pop ebx //恢复EBX end;
编辑1: 关于的说明: 这当然是基于>= 32位的x86处理器(80386或更高版本),但Delphi Win32代码在早期机器上也无法运行。CPUID指令是在晚期80486处理器中引入的。
由于Delphi现在可以编译Win64,我想分享我的解决方案:
function WindowsBits: integer;
function IsWow64: Boolean;
{$IFDEF WIN64}
begin
// Native 64 Bit App means OS and CPU is 64 Bit, too.
result := false;
{$ELSE}
type
TIsWow64Process = function( // Type of IsWow64Process API fn
Handle: Windows.THandle; var Res: Windows.BOOL
): Windows.BOOL; stdcall;
var
IsWow64Result: Windows.BOOL; // Result from IsWow64Process
IsWow64Process: TIsWow64Process; // IsWow64Process fn reference
begin
// Try to load required function from kernel32
IsWow64Process := Windows.GetProcAddress(
Windows.GetModuleHandle('kernel32'), 'IsWow64Process'
);
if Assigned(IsWow64Process) then
begin
// Function is implemented: call it
if not IsWow64Process(
Windows.GetCurrentProcess, IsWow64Result
) then
raise SysUtils.Exception.Create('IsWow64: bad process handle');
// Return result of function
Result := IsWow64Result;
end
else
// Function not implemented: can't be running on Wow64
Result := False;
{$ENDIF}
end;
begin
{$IFDEF WIN64}
result := 64;
{$ELSE}
if IsWow64 then
result := 64
else
result := 32;
{$ENDIF}
end;
if SizeOf(Pointer)=8 then
Exit(True); // Current app is 64 bit
如果 sizeof(IntPtr) == 8
,则您是在64位Windows上的64位应用程序(编辑:仅适用于Delphi Prism)
否则,如果{{link1:IsWow64Process
}}成功并返回true,则您是在64位Windows上的32位应用程序
否则,您将在32位Windows上