Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if the processor is 64-bit under 32 bit OS

Normally, x86-64 architecture offers compatibility with x86. A 32-bit Windows (or other OS) can run on an x86-64 processor. (Correct me if I am wrong).

I would like to know if it is possible (in C++) for a 32-bit Windows to know that if underlying processor is 64-bit. For example, if Windows 7 32-bit running on Core i5, we should be able to know that processor is 64-bit (although Windows 7 32 bit is running).

You may question the requirement that even if processor is 64 bit and OS is 32 bit, 64 bit processes cannot run (Correct me if I am wrong). But the aim of the program to know the processor, not OS. This question may appear similar to this, but it does not give any hint of C++ program.

like image 316
doptimusprime Avatar asked Aug 31 '12 09:08

doptimusprime


2 Answers

This is not a C++ solution, but it seems to work in C#.
However should be easily converted to C++ because the key point is in the API structure SYSTEM_INFO and the API GetNativeSystemInfo()

First a reference to the API that gets infos

[DllImport("kernel32.dll")]
public static extern void GetNativeSystemInfo
              ([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);

then the structure SYSTEM_INFO and the _PROCESSOR_INFO_UNION

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
    internal _PROCESSOR_INFO_UNION uProcessorInfo;
    public uint dwPageSize;
    public IntPtr lpMinimumApplicationAddress;
    public IntPtr lpMaximumApplicationAddress;
    public IntPtr dwActiveProcessorMask;
    public uint dwNumberOfProcessors;
    public uint dwProcessorType;
    public uint dwAllocationGranularity;
    public ushort dwProcessorLevel;
    public ushort dwProcessorRevision;
}

[StructLayout(LayoutKind.Explicit)]
public struct _PROCESSOR_INFO_UNION
{
    [FieldOffset(0)]
    internal uint dwOemId;
    [FieldOffset(0)]
    internal ushort wProcessorArchitecture;
    [FieldOffset(2)]
    internal ushort wReserved;
}

Now an enum to simplify the code and the method that calls the native API

public enum ProcessorArchitecture
{
    Unknown = 0,
    Bit32 = 1,
    Bit64 = 2,
    Itanium64 = 3
}

static public ProcessorArchitecture ProcessorBits
{
    get
    {
        ProcessorArchitecture pbits = ProcessorArchitecture.Unknown;
        SYSTEM_INFO l_System_Info = new SYSTEM_INFO();
        GetNativeSystemInfo(ref l_System_Info);

        switch (l_System_Info.uProcessorInfo.wProcessorArchitecture)
        {
            case 9: // PROCESSOR_ARCHITECTURE_AMD64
                pbits = ProcessorArchitecture.Bit64;
                break;
            case 6: // PROCESSOR_ARCHITECTURE_IA64
                pbits = ProcessorArchitecture.Itanium64;
                break;
            case 0: // PROCESSOR_ARCHITECTURE_INTEL
                pbits = ProcessorArchitecture.Bit32;
                break;
            default: // PROCESSOR_ARCHITECTURE_UNKNOWN
                pbits = ProcessorArchitecture.Unknown;
                break;
        }
        return pbits;
    }
}
like image 125
Steve Avatar answered Oct 16 '22 20:10

Steve


Well, as far as I am aware, you can only get this through looking at the CPU information itself. I think it should be enough (for x86 & amd64) to check whether the CPU supports long mode.

For that, you could use the cpuid instruction on x86. By Windows-ness of your post, I'll take a guess you're using the Microsoft C++ compiler. For that, there's a __cpuid intrinsic. Sadly, the description on Microsoft's page ends at PBE flag, while lm flag in my cpuinfo goes three flags later.

Looking at CPUID Modifications for AMD Processors, you can get LM with InfoType = 0x80000001, with the result being at bit 29 of the last returned integer. In CPUID Modifications for Intel Processors the same bit specifies EM64T flag which is equivalent AFAIK.

In both cases, you should be doing InfoType = 0x80000000 first to get maximum meaningful InfoType value. If it's less than 0x80000001, then you should not do the above check and instead assume long mode is not supported.

like image 6
Michał Górny Avatar answered Oct 16 '22 20:10

Michał Górny