我怎么知道我是否在x64上运行?

问题描述 投票:9回答:6

我刚刚收到一个错误报告,该错误报告仅在程序“在64位计算机上”运行时才会发生。现在,Delphi不会产生64位代码,因此从理论上讲这并不重要,但显然在这种情况下它会产生。我认为我有一种解决方法,但是它将在32位Windows上使事情中断,因此我需要一些方法来告诉:

  1. 如果我在x64或x86处理器上运行,并且
  2. 如果我在Win32仿真或32位操作系统上的本机Win32下在64位版本的Windows下运行。

有人知道我如何从我的应用程序中获得这些答案吗?

delphi 64-bit
6个回答
21
投票

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;

再见。


8
投票

我看到您的问题2(您在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 //IF CPUID.80000001h.EDX[bit29]=1 THEN it's a 64bit processor. //But we first need to check whether there's a function 80000001h. push ebx //Save EBX as CPUID will modify EBX push esi //Save ESI as we'll use ESI internally

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 //Result{AL/EAX}:=0{false; it's a 32-bit processor}; @Exit: pop esi //Restore ESI pop ebx //Restore EBX end;

EDIT1:关于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} 的注释:当然,这是假定> = 32位x86处理器(80386或更高版本),但是Delphi Win32代码无论如何都不会在较早的计算机上运行。最新的80486处理器引入了CPUID指令。


3
投票

您可以检查是否存在,然后呼叫CPUIDavailable。链接的MSDN页面显示所需的代码。


2
投票

MSDN页面上说:

为了与不支持此功能的操作系统兼容函数,调用GetProcAddress以检测IsWow64Process是否为在Kernel32.dll中实现。如果GetProcAddress成功,则可以安全地进行调用此函数。否则,不存在WOW64。注意这个技术不是检测操作系统是否可靠的方法是Windows的64位版本,因为当前的Kernel32.dll32位Windows版本也包含此功能。

这意味着:这是一个新功能,您必须小心地静态链接到它。


0
投票

在第一个功能的开头,您需要添加

IsWow64Process

-1
投票

[if if SizeOf(Pointer)=8 then Exit(True); // Current app is 64 bit 您是64位Windows上的64位应用程序(edit:仅适用于Delphi Prism)

否则,如果sizeof(IntPtr) == 8成功并返回true,则说明您是32位应用程序,64位Windows

else您使用的是32位Windows

© www.soinside.com 2019 - 2024. All rights reserved.