Как я могу узнать, что я работаю на x64? - PullRequest
9 голосов
/ 17 сентября 2009

Я только что получил отчет об ошибке, которая возникает, только когда программа работает «на 64-битной машине». Теперь Delphi не создает 64-битный код, поэтому теоретически это не должно иметь значения, но, очевидно, в этом случае это так. Я думаю, что у меня есть обходной путь, но он сломает вещи на 32-битной Windows, поэтому мне нужно как-то сказать:

  1. Если я работаю на процессоре x64 или x86 и
  2. Если я работаю под 64-битной версией Windows под эмуляцией Win32 или с родной Win32 в 32-битной ОС.

Кто-нибудь знает, как я могу получить эти ответы из моего приложения?

Ответы [ 5 ]

20 голосов
/ 17 сентября 2009

Мейсон, вы можете использовать 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;

Bye.

8 голосов
/ 17 сентября 2009

Я вижу, что на ваш вопрос 2 (вы работаете на Win64?) Уже дан ответ. Просто помните, что для того, чтобы ваш код был ориентирован на будущее, вы должны учитывать, что в (гипотетическом) 64-битном приложении Delphi, работающем на Win64, IsWow64Process также будет возвращать FALSE.

Что касается вашего первого вопроса - у вас 64-битный ЦП - вы можете проверить аппаратное обеспечение на наличие соответствующего флага функции CPUID, как показано в приведенном ниже коде.

<code>
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;</p>

<p>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</p>

<pre><code>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 {false; это 32-битный процессор}; @Выход: pop esi // Восстановление ESI pop ebx // Восстановление EBX конец;

EDIT1: примечание к CPUIDavailable: Это, конечно, предполагается, что> = 32-битный процессор x86 (80386 или новее), но Delphi Win32-код все равно не будет работать на более ранних машинах. Инструкция CPUID была введена в конце 80486 процессоров.

3 голосов
/ 17 сентября 2009

Вы можете проверить наличие и затем вызвать IsWow64Process . На связанной странице MSDN показан требуемый код.

2 голосов
/ 02 ноября 2012

На странице MSDN написано:

Для совместимости с операционными системами, которые не поддерживают это вызовите функцию GetProcAddress, чтобы определить, является ли IsWow64Process реализовано в Kernel32.dll. Если GetProcAddress завершается успешно, безопасно вызвать эту функцию. В противном случае WOW64 нет. Обратите внимание, что это Техника не является надежным способом определить, является ли операционная система это 64-разрядная версия Windows, потому что Kernel32.dll в текущем версии 32-битной Windows также содержат эту функцию.

Что означает: это новая функция, и вы должны быть статически привязаны к ней.

0 голосов
/ 17 сентября 2009

если sizeof(IntPtr) == 8 вы - 64-битное приложение в 64-битной Windows ( edit: применимо только к Delphi Prism)

иначе, если IsWow64Process завершится успешно и вернет true , вы 32-битное приложение на 64-битная Windows

иначе вы используете 32-разрядную версию Windows

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...