测试CPU的特性

这段代码用于检测CPU是否支持SSE、SSE2等特性,适用于Windows环境下,通过Intel CPUID指令获取CPU特性,并进行解析。程序包括了检查SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、PCLMULQDQ、AES-NI等特性的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
功能:测试CPU的特性
测试环境:Windows 8.1 64bit、Visual Studio 2013 Update1、Core i5-2500k
最后更新日期:2014-04-23 kagula
描述:我忘记这段代码从哪里download下来,但是经测试可以用,
通过这段代码的学习, 可以写一个测试CPU是否支持SSE/SSE2特性的函数。
如何运行源代码:在Visual Studio 2013下建立Windows Console项目,然后加入这个源代码编译,运行即可。
*/
#include "stdafx.h"

#include <stdio.h>
#include <stdint.h>
#include <string.h>

enum {
	CPU_X86_FEATURE_SSE    = (1 << 1),
	CPU_X86_FEATURE_SSE2   = (1 << 2),
	CPU_X86_FEATURE_SSE3   = (1 << 3),
	CPU_X86_FEATURE_SSSE3  = (1 << 4),
	CPU_X86_FEATURE_SSE4_1 = (1 << 5),
	CPU_X86_FEATURE_SSE4_2 = (1 << 6),
	CPU_X86_FEATURE_POPCNT = (1 << 7),
	CPU_X86_FEATURE_MOVBE  = (1 << 8),
	CPU_X86_FEATURE_AESNI  = (1 << 9),
	CPU_X86_FEATURE_RDRND  = (1 << 10),
	CPU_X86_FEATURE_PCLMULQDQ = (1 << 11),
	CPU_X86_FEATURE_SMEP      = (1 << 12), // CPUID.7.0.EBX[7] OS Guard
	CPU_X86_FEATURE_SHA       = (1 << 13), // CPUID.7.0.EBX[29] http://software.intel.com/en-us/articles/intel-sha-extensions
	CPU_X86_FEATURE_ADX       = (1 << 14), // CPUID.(EAX=07H, ECX=0H):EBX.ADX[bit 19]=1 indicates the processor supports ADCX and ADOX instructions
	CPU_X86_FEATURE_RDSEED    = (1 << 15), // Hardware support for the RDSEED instruction is indicated by CPUID.(EAX=07H,ECX=0H):EBX.RDSEED[bit 18].
};

static uint64_t g_cpu_features = 0;

#ifdef WIN32
#include <intrin.h>
#else
static void __cpuidex(unsigned int where[4], unsigned int leaf, unsigned int ECXValue) {
	asm volatile("cpuid":"=a"(*where), "=b"(*(where + 1)), "=c"(*(where + 2)), "=d"(*(where + 3)) : "a"(leaf), "c"(ECXValue));
	return;
}

static void __cpuid(unsigned int where[4], unsigned int leaf) {
	asm volatile("cpuid":"=a"(*where), "=b"(*(where + 1)), "=c"(*(where + 2)), "=d"(*(where + 3)) : "a"(leaf));
	return;
}
#endif


static int get_cpu_features() {
	int cpuid_results[4];
	__cpuid(cpuid_results, 0);

	if (cpuid_results[0] < 1)
		return 0;
	/*
	*      MSB         LSB
	* EBX = 'u' 'n' 'e' 'G'
	* EDX = 'I' 'e' 'n' 'i'
	* ECX = 'l' 'e' 't' 'n'
	*/
	/* According to http://en.wikipedia.org/wiki/CPUID */

	if (memcmp((unsigned char *)&cpuid_results[1], "Genu", 4) != 0 ||
		memcmp((unsigned char *)&cpuid_results[3], "ineI", 4) != 0 ||
		memcmp((unsigned char *)&cpuid_results[2], "ntel", 4) != 0)
		return 0;

	__cpuid(cpuid_results, 1);
	printf("CPUID.1.ECX 0x%08x:\n", cpuid_results[2]);
	if ((cpuid_results[2] & (1 << 1)) != 0) {
		// CPUID.1.ECX[1]
		g_cpu_features |= CPU_X86_FEATURE_PCLMULQDQ;
	}
	if ((cpuid_results[2] & (1 << 9)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSSE3;
	}
	if ((cpuid_results[2] & (1 << 23)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_POPCNT;
	}
	if ((cpuid_results[2] & (1 << 25)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_AESNI; // aes-ni
	}
	if ((cpuid_results[2] & (1 << 30)) != 0) {
		//RDRAND is not an AVX instruction. It is a normal instruction.
		g_cpu_features |= CPU_X86_FEATURE_RDRND; // secure key
	}
	// vendorIsIntel
	if ((cpuid_results[2] & (1 << 22)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_MOVBE;
	}

	if ((cpuid_results[2] & (1 << 25)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSE; 
	}
	if ((cpuid_results[2] & (1 << 26)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSE2; 
	}
	if ((cpuid_results[2] & (1 << 0)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSE3; 
	}
	if ((cpuid_results[2] & (1 << 19)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSE4_1; 
	}
	if ((cpuid_results[2] & (1 << 20)) != 0) {
		g_cpu_features |= CPU_X86_FEATURE_SSE4_2; 
	}

	// Look for CPUID.7.0.EBX
	// EAX = 7, ECX = 0
	__cpuidex(cpuid_results, 7, 0);
	printf("CPUID.7.0.EBX 0x%08x:\n", cpuid_results[1]);
	if ((cpuid_results[1] & (1 << 7)) != 0) {
		// SMEP is identified by CPUID leaf 7 EBX[7], which is 0 before
		// CPUID.7.0.EBX[7]
		g_cpu_features |= CPU_X86_FEATURE_SMEP;
	}
	if ((cpuid_results[1] & (1 << 18)) != 0) {
		// Intel® RDSEED Extensions
		// CPUID.7.0.EBX[18]
		g_cpu_features |= CPU_X86_FEATURE_RDSEED;
	}
	if ((cpuid_results[1] & (1 << 19)) != 0) {
		// Intel® ADX Extensions
		// CPUID.7.0.EBX[19]
		g_cpu_features |= CPU_X86_FEATURE_ADX;
	}
	if ((cpuid_results[1] & (1 << 29)) != 0) {
		// Intel® SHA Extensions
		// CPUID.7.0.EBX[29]
		g_cpu_features |= CPU_X86_FEATURE_SHA;
	}



	return 1;
}

struct cpu_features {
	char name[16];
	int value;
};

struct cpu_features cpu_x86_features[] = {
	{ "SSE ", CPU_X86_FEATURE_SSE },
	{ "SSE2 ", CPU_X86_FEATURE_SSE2 },
	{ "SSE3 ", CPU_X86_FEATURE_SSE3 },
	{ "SSSE3 ", CPU_X86_FEATURE_SSSE3 },
	{ "SSE4_1 ", CPU_X86_FEATURE_SSE4_1 },
	{ "SSE4_2 ", CPU_X86_FEATURE_SSE4_2 },
	{ "PCLMULQDQ ", CPU_X86_FEATURE_PCLMULQDQ },
	{ "AES-NI ", CPU_X86_FEATURE_AESNI },
	{ "RDRAND ", CPU_X86_FEATURE_RDRND },
	{ "SMEP ", CPU_X86_FEATURE_SMEP },
	{ "SHA ", CPU_X86_FEATURE_SHA },
	{ "ADX ", CPU_X86_FEATURE_ADX },
	{ "RDSEED ", CPU_X86_FEATURE_RDSEED }
};

int _tmain(int argc, _TCHAR* argv[])
{
	int i = 0, num = 0;
	if (0 == g_cpu_features)
		get_cpu_features();
	printf("This cpu features 0x%08x:\n", g_cpu_features);

	num = sizeof(cpu_x86_features) / sizeof(struct cpu_features);
	for (i = 0; i < num; i++) {
		printf(cpu_x86_features[i].name);
		if (g_cpu_features & cpu_x86_features[i].value)
		{
			printf("support\n");
		}
		else
		{
			printf("not support\n");

		}
	}
	
	//输入一个字符后,程序返回!
	getchar();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kagula086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值