C语言方式 获取CPUID(二)

这段代码展示了如何在IA-32和x64架构上使用内联汇编执行CPUID指令来获取CPU的版本信息。`AsmCpuid`函数接受一个索引参数并返回CPUID指令后的EAX、EBX、ECX和EDX寄存器的值。在示例中,主要关注EAX寄存器中的CPU版本信息,并打印出来。
摘要由CSDN通过智能技术生成

代码采用的是嵌入汇编(内联汇编)方式,只适用于IA-32和x64架构。参考的是EDKII内核中的源代码。
\MdePkg\Library\BaseLib\Ia32\CpuId.c

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned int UINT32;
#define IN
#define OUT
#define OPTIONAL
#define EFIAPI
#define CPUID_VERSION_INFO  0x01
#define CPUID_FULL_FAMILY_MODEL                    0x0FFF0FF0
typedef UINT32       CPU_FAMILY;

/**
  CPUID Version Information returned in EAX for CPUID leaf
  #CPUID_VERSION_INFO.
**/
typedef union {
    ///
    /// Individual bit fields
    ///
    struct {
        UINT32    SteppingId : 4; ///< [Bits   3:0] Stepping ID
        UINT32    Model : 4; ///< [Bits   7:4] Model
        UINT32    FamilyId : 4; ///< [Bits  11:8] Family
        UINT32    ProcessorType : 2; ///< [Bits 13:12] Processor Type
        UINT32    Reserved1 : 2; ///< [Bits 15:14] Reserved
        UINT32    ExtendedModelId : 4; ///< [Bits 19:16] Extended Model ID
        UINT32    ExtendedFamilyId : 8; ///< [Bits 27:20] Extended Family ID
        UINT32    Reserved2 : 4; ///< Reserved
    } Bits;
    ///
    /// All bit fields as a 32-bit value
    ///
    UINT32    Uint32;
} CPUID_VERSION_INFO_EAX;


/**
  Retrieves CPUID information.

  Executes the CPUID instruction with EAX set to the value specified by Index.
  This function always returns Index.
  If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
  If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
  If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
  If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
  This function is only available on IA-32 and x64.

  @param  Index         The 32-bit value to load into EAX prior to invoking the CPUID
                        instruction.
  @param  RegisterEax   A pointer to the 32-bit EAX value returned by the CPUID
                        instruction. This is an optional parameter that may be NULL.
  @param  RegisterEbx   A pointer to the 32-bit EBX value returned by the CPUID
                        instruction. This is an optional parameter that may be NULL.
  @param  RegisterEcx   A pointer to the 32-bit ECX value returned by the CPUID
                        instruction. This is an optional parameter that may be NULL.
  @param  RegisterEdx   A pointer to the 32-bit EDX value returned by the CPUID
                        instruction. This is an optional parameter that may be NULL.

  @return Index.

**/
UINT32
EFIAPI
AsmCpuid(
    IN      UINT32  Index,
    OUT     UINT32* RegisterEax   OPTIONAL,
    OUT     UINT32* RegisterEbx   OPTIONAL,
    OUT     UINT32* RegisterEcx   OPTIONAL,
    OUT     UINT32* RegisterEdx   OPTIONAL
)
{
    _asm {
        mov     eax, Index
        cpuid
        push    ecx
        mov     ecx, RegisterEax
        jecxz   SkipEax
        mov[ecx], eax
    SkipEax :
        mov     ecx, RegisterEbx
        jecxz   SkipEbx
        mov[ecx], ebx
    SkipEbx :
        pop     eax
        mov     ecx, RegisterEcx
        jecxz   SkipEcx
        mov[ecx], eax
    SkipEcx :
        mov     ecx, RegisterEdx
        jecxz   SkipEdx
        mov[ecx], edx
    SkipEdx :
        mov     eax, Index
    }
}


int main()
{
    CPUID_VERSION_INFO_EAX  Eax;
    CPU_FAMILY family;
    AsmCpuid(CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
    family = Eax.Uint32& CPUID_FULL_FAMILY_MODEL;
    printf("EAX:%08X\n", Eax.Uint32);
	system("pause");
}

结果:
运行结果

C语言可以通过使用Windows和Linux操作系统提供的相关 API 来获取本机的 CPUID 和 MAC 地址。 首先,我们可以通过Windows API函数`GetSystemInfo()`获取CPUID。示例代码如下: ```c #include <stdio.h> #include <windows.h> void main() { SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); printf("CPU ID: %x %x %x %x\n", sys_info.dwProcessorType, sys_info.dwPageSize, sys_info.dwActiveProcessorMask, sys_info.dwNumberOfProcessors); } ``` 然后,我们可以通过使用Windows API函数`GetAdaptersInfo()`来获取本机的 MAC 地址。示例代码如下: ```c #include <stdio.h> #include <windows.h> #include <iphlpapi.h> #pragma comment(lib, "iphlpapi.lib") void main() { IP_ADAPTER_INFO adapter_info[16]; DWORD buf_len = sizeof(adapter_info); if (GetAdaptersInfo(adapter_info, &buf_len) == ERROR_SUCCESS) { PIP_ADAPTER_INFO curr_adapter = adapter_info; while (curr_adapter != NULL) { printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", curr_adapter->Address[0], curr_adapter->Address[1], curr_adapter->Address[2], curr_adapter->Address[3], curr_adapter->Address[4], curr_adapter->Address[5]); curr_adapter = curr_adapter->Next; } } } ``` 对于Linux操作系统,我们可以使用`sys/sysinfo.h`和`ifaddrs.h`头文件来获取 CPUID 和 MAC 地址。示例代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/sysinfo.h> #include <ifaddrs.h> #include <netinet/in.h> #include <arpa/inet.h> #include <net/if.h> #include <string.h> void main() { struct sysinfo sys_info; if (sysinfo(&sys_info) == 0) { printf("CPU ID: %08x\n", (unsigned int)sys_info.processor_id[0]); } struct ifaddrs* ifaddr, *ifa; if (getifaddrs(&ifaddr) == 0) { for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_PACKET) continue; struct sockaddr_ll* s = (struct sockaddr_ll*)ifa->ifa_addr; unsigned char mac[6]; memcpy(mac, s->sll_addr, 6); printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } freeifaddrs(ifaddr); } } ``` 需要注意的是,在使用这些API函数时,可能需要添加某些特定的库文件或在编译选项中指定相关的库文件,具体需要根据不同的操作系统和编译环境来进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值