首页
社区
课程
招聘
[原创]科普一下CPUID的正确用法
2009-7-8 11:26 7359

[原创]科普一下CPUID的正确用法

2009-7-8 11:26
7359
使用了cpuid指令的程序要想通用的话:

1.判断SPU是否支持cpuid指令
方法:看eflags的第21位(ID位)能否被改变
BOOL __declspec(naked) IsCpuidValid()
{
	__asm
	{
		pushfd
		pop eax             //eax = eflags
		mov ebx, eax
		xor eax, 00200000h  //toggle bit 21, eflags.[ID]
		push eax
		popfd
		pushfd
		pop eax
		cmp eax, ebx
		jz NO_CPUID
		mov eax, 1
		ret
NO_CPUID:
		xor eax, eax
		ret
	}
}


2.如果cpu支持cpuid指令,在使用某一cpuid function num之前
先判断是否支持该function num:

    CPUID_ARGS ca;
    ca.eax = 0;
    cpuid32(&ca);
    char Vendor[13];
    *((PULONG)&Vendor[0]) = ca.ebx;
    *((PULONG)&Vendor[4]) = ca.edx;
    *((PULONG)&Vendor[8]) = ca.ecx;
    Vendor[12] = '\0';

    printf("CPU Vendor: %s\n", Vendor);
    printf("Max Standard function: 0x%08x\n", ca.eax);

    ca.eax = 0x80000000;
    cpuid32(&ca);

    printf("Max Extended function: 0x%08x\n", ca.eax);


3.参考相应处理器厂商的手册规范使用相应的function num
if(strcmp(Vendor, "GenuineIntel") == 0)
{
    //参考IPM-241618
    if(ca.eax >= 0x80000004) //support brand string
    {
        char Brand[48];
        ca.eax = 0x80000002;
        cpuid32(&ca);
        *((PULONG)&Brand[0]) = ca.eax;
        *((PULONG)&Brand[4]) = ca.ebx;
        *((PULONG)&Brand[8]) = ca.ecx;
        *((PULONG)&Brand[12]) = ca.edx;

        ca.eax = 0x80000003;
        cpuid32(&ca);
        *((PULONG)&Brand[16]) = ca.eax;
        *((PULONG)&Brand[20]) = ca.ebx;
        *((PULONG)&Brand[24]) = ca.ecx;
        *((PULONG)&Brand[28]) = ca.edx;

        ca.eax = 0x80000004;
        cpuid32(&ca);
        *((PULONG)&Brand[32]) = ca.eax;
        *((PULONG)&Brand[36]) = ca.ebx;
        *((PULONG)&Brand[40]) = ca.ecx;
        *((PULONG)&Brand[44]) = ca.edx;

        printf("Brand: %s\n", Brand);
    }
}
else if(strcmp(Vendor, "AuthenticAMD") == 0)
{
    //参考APM-25481
    if(ca.eax >= 0x80000004) //support brand string
    {
        char Brand[48];
        ca.eax = 0x80000002;
        cpuid32(&ca);
        *((PULONG)&Brand[0]) = ca.eax;
        *((PULONG)&Brand[4]) = ca.ebx;
        *((PULONG)&Brand[8]) = ca.ecx;
        *((PULONG)&Brand[12]) = ca.edx;

        ca.eax = 0x80000003;
        cpuid32(&ca);
        *((PULONG)&Brand[16]) = ca.eax;
        *((PULONG)&Brand[20]) = ca.ebx;
        *((PULONG)&Brand[24]) = ca.ecx;
        *((PULONG)&Brand[28]) = ca.edx;

        ca.eax = 0x80000004;
        cpuid32(&ca);
        *((PULONG)&Brand[32]) = ca.eax;
        *((PULONG)&Brand[36]) = ca.ebx;
        *((PULONG)&Brand[40]) = ca.ecx;
        *((PULONG)&Brand[44]) = ca.edx;

        printf("Brand: %s\n", Brand);
    }
}
else //if(...)
{
    //参考其他处理器厂商手册
}



详见附件源码

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (4)
雪    币: 193
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cham 2009-7-8 15:07
2
0
关于function num,Intel貌似是这样处理的:
1.如果num的最高位为0,并且大于允许的max num的话,就和max num是一样的吧;
2.如果num的最高位为1,并且大于允许的max num的话,最高位将被置0,接下来就参照1.
不知道amd是不是也这样的,好像没看到有说明。
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 2009-7-8 22:39
3
0
完全看不懂,但是帖子还是要顶的。因为diyhack是个好人。
雪    币: 1753
活跃值: (660)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
cmdxhz 1 2009-7-9 23:49
4
0
呵呵`~
  不错哦~~~感谢了~`
这好解决了  我那个获取 CPU信息代码 的判断`是否对该指令的支持问题~!
雪    币: 1753
活跃值: (660)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
cmdxhz 1 2009-7-9 23:57
5
0
厉害啊~`
         比我考虑``周到多了~`
当时我只是粗粗的看了下相关的知识``
搞了一个读取CPU信息的东西`
  没考虑到`是否支持CPUID 这个指令~!
游客
登录 | 注册 方可回帖
返回