C语言调用Intel处理器CPUID指令的实例
C语言调用Intel处理器CPUID指令的实例
来源 https://blog.csdn.net/subfate/article/details/50789905
在Linux环境下,使用C语言内嵌汇编的手段使用CPUID指令,进而在高级语言层面上看到获取的信息。
实现文件cpuid.c代码如下:
struct cpuid_result {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
}; /*
* Generic CPUID function
*/
static inline struct cpuid_result cpuid(unsigned int op)
{
struct cpuid_result result;
__asm volatile(
"mov %%ebx, %%edi;"
"cpuid;"
"mov %%ebx, %%esi;"
"mov %%edi, %%ebx;"
: "=a" (result.eax),
"=S" (result.ebx),
"=c" (result.ecx),
"=d" (result.edx)
: "" (op)
: "edi");
return result;
} static inline unsigned int cpuid_eax(unsigned int op)
{
//unsigned int eax, ebx, ecx, edx;
struct cpuid_result regs; regs = cpuid(op); return regs.eax;
} void get_cpu_vendor(char* cpu_vendor, unsigned int* cpuid_level)
{
unsigned int cpuid_op = 0x00000000;
char vendor_name[] = {'\0'};
struct cpuid_result result;
unsigned int level = ; vendor_name[] = '\0'; /* Unset */
result = cpuid(cpuid_op); // eax为0表示读取vendor id,一共12字节,依次在ebx、edx、ecx。
level = result.eax;
vendor_name[] = (result.ebx >> ) & 0xff;
vendor_name[] = (result.ebx >> ) & 0xff;
vendor_name[] = (result.ebx >> ) & 0xff;
vendor_name[] = (result.ebx >> ) & 0xff;
vendor_name[] = (result.edx >> ) & 0xff;
vendor_name[] = (result.edx >> ) & 0xff;
vendor_name[] = (result.edx >> ) & 0xff;
vendor_name[] = (result.edx >> ) & 0xff;
vendor_name[] = (result.ecx >> ) & 0xff;
vendor_name[] = (result.ecx >> ) & 0xff;
vendor_name[] = (result.ecx >> ) & 0xff;
vendor_name[] = (result.ecx >> ) & 0xff;
vendor_name[] = '\0'; strcpy(cpu_vendor, vendor_name);
*cpuid_level = level;
} void get_cpu_id(char* cpu_id, unsigned int* cpu_sign)
{
unsigned int cpuid_op = 0x00000001;
struct cpuid_result result;
unsigned int sign = , id = ;
unsigned int tmp = ; result = cpuid(cpuid_op);
sign = result.eax;
id = result.edx; sprintf(cpu_id, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", (sign >> ) & 0xff, (sign >> ) & 0xff, (sign >> ) & 0xff, (sign >> ) & 0xff,
(id >> ) & 0xff, (id >> ) & 0xff, (id >> ) & 0xff, (id >> ) & 0xff);
*cpu_sign = sign;
} struct cpuinfo_x86 {
uint8_t x86; /* CPU family */
uint8_t x86_vendor; /* CPU vendor */
uint8_t x86_model; /* CPU model */
uint8_t x86_step; /* CPU stepping */
}; // 参考IA32开发手册第2卷第3章。CPUID exa==0x01的图3-6
static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
{
c->x86 = (tfms >> ) & 0xf;
c->x86_model = (tfms >> ) & 0xf;
c->x86_step = tfms & 0xf;
if (c->x86 == 0xf)
c->x86 += (tfms >> ) & 0xff;
if (c->x86 >= 0x6)
c->x86_model += ((tfms >> ) & 0xF) << ;
} void get_cpu_fms(unsigned int* family, unsigned int* model, unsigned int* stepping)
{
unsigned int cpuid_op = 0x00000001;
struct cpuinfo_x86 c;
unsigned int ver = ; ver = cpuid_eax(cpuid_op);
get_fms(&c, ver); *family = c.x86;
*model = c.x86_model;
*stepping = c.x86_step;
} void get_cpu_name(char* processor_name)
{
unsigned int cpuid_op = 0x80000002;
struct cpuid_result regs;
char temp_processor_name[];
char* processor_name_start;
unsigned int *name_as_ints = (unsigned int *)temp_processor_name;
unsigned int i; /*
用cpuid指令,eax传入0x80000002/0x80000003/0x80000004,
共3个,每个4个寄存器,每个寄存器4字节,故一共48字节。
参考IA32开发手册第2卷第3章。
*/
for (i = ; i < ; i++) {
regs = cpuid(cpuid_op + i);
name_as_ints[i * + ] = regs.eax;
name_as_ints[i * + ] = regs.ebx;
name_as_ints[i * + ] = regs.ecx;
name_as_ints[i * + ] = regs.edx;
} temp_processor_name[] = '\0'; // 最后的字节为0,结束 /* Skip leading spaces. */
processor_name_start = temp_processor_name;
while (*processor_name_start == ' ')
processor_name_start++; memset(processor_name, , );
strcpy(processor_name, processor_name_start);
} void get_address_bits(unsigned int* linear, unsigned int* physical)
{
unsigned int cpuid_op = 0x80000008;
unsigned int tmp = ;
tmp = cpuid_eax(cpuid_op);
*linear = (tmp >> ) & 0xff;
*physical = (tmp >> ) & 0xff; }
主函数实现代码如下:
void get_hw_cpu(void)
{
char buffer[] = { '\0' };
unsigned int num = ;
unsigned int f = , m = , s = ;
unsigned int phy_bits = , vir_bits = ; memset((void *)buffer, '\0', sizeof(buffer));
num = ;
get_cpu_vendor(buffer, &num);
fprintf(stdout, "vendor_id \t: %s\n", buffer);
fprintf(stdout, "cpuid level \t: %u\n", num); memset((void *)buffer, '\0', sizeof(buffer));
num = ;
get_cpu_id(buffer, &num);
fprintf(stdout, "cpu_id serial \t: %s\n", buffer);
fprintf(stdout, "cpuid sign \t: %u\n", num); memset((void *)buffer, '\0', sizeof(buffer));
get_cpu_name(buffer);
fprintf(stdout, "model name \t: %s\n", buffer); get_cpu_fms(&f, &m, &s);
fprintf(stdout, "cpu family \t: %u(0x%0X)\n", f, f);
fprintf(stdout, "cpu model \t: %u(0x%0X)\n", m, m);
fprintf(stdout, "cpu stepping \t: %u(0x%0X)\n", s, s); get_address_bits(&vir_bits, &phy_bits);
fprintf(stdout, "address sizes \t: %u bits physical - %u bits virtual\n", phy_bits, vir_bits); }
Intel处理器的CPUID远不止上文所述,详情请参考Intel IA32软件开发手册。
在GCC中获取CPUID信息(兼容VC) https://www.cnblogs.com/zyl910/archive/2012/08/06/getcpuid_gcc.html
=========================== End
C语言调用Intel处理器CPUID指令的实例的更多相关文章
- CPUID指令简单调用
关于CPUID指令,可以看维基百科的相关介绍 https://en.wikipedia.org/wiki/CPUID 在windows下可以调用__cpuid和__cpuidex这两个函数,__cpu ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma checksum(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma checksum(C# 参考) 1.返回顶部 1. #pragma checksum(C# 参考) 2015/0 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma warning(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma warning(C# 参考) 1.返回顶部 1. #pragma warning(C# 参考) 2015/07/ ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma(C# 参考) 1.返回顶部 1. #pragma(C# 参考) 2015/07/20 #pragma 为编译器给 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#endregion(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#endregion(C# 参考) 1.返回顶部 1. #endregion(C# 参考) 2015/07/20 #endreg ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#region(C# 参考) 1.返回顶部 1. #region(C# 参考) 2015/07/20 利用 #region,可以 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#line(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#line(C# 参考) 1.返回顶部 1. #line(C# 参考) 2015/07/20 借助 #line,可修改编译器的行 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#error(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#error(C# 参考) 1.返回顶部 1. #error(C# 参考) 2015/07/20 #error 可从代码中的特定 ...
- Docs-.NET-C#-指南-语言参考-预处理器指令:#warning(C# 参考)
ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#warning(C# 参考) 1.返回顶部 1. #warning(C# 参考) 2015/07/20 #warning 允许 ...
随机推荐
- 成都Uber优步司机奖励政策(3月16日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 成都Uber优步司机奖励政策(2月23日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- linq中group by 的用法
如下代码: var dates=(from p in points group p by p.LevelId into g select new { g.Key,g });之后 你会拿到这个数组: 之 ...
- spring-boot、spring-data-jpa、hibernate整合
一.Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置. ...
- 「Python」Numpy equivalent of MATLAB's cell array
转自Stackoverflow.备忘用. Question I want to create a MATLAB-like cell array in Numpy. How can I accompli ...
- Qt-QML-Popup,弹层界面编写
随着接触Qt的时间的增加,也逐渐的发现了Qt 的一些不人信话的一些地方,不由的想起一句话,也不知道是在哪里看到的了“一切变成语言都是垃圾,就C++还可以凑合用”大致意思是这样.最近项目的祝界面框架都基 ...
- gitlab-登录账户遇到ERROR: Permission to XXX.git denied to user报错怎么办
碰到这个问题就意味着没有访问账户的权限,没有把访问电脑与访问账户用ssh_key关联起来,解决流程: 1.查看本地是否有ssh_key 笔者用的是git bash来输入命令 ls -al ~/.ssh ...
- java字符转义
之前对java字符转义这一块稍作了解,在这里理理自己主观浅显的理解 这里会谈谈字符编码的是另一种问题和转义没有关系 以下面代码做分析 System.out.println("a". ...
- Python对文本文件逐行扫描,将含有关键字的行存放到另一文件
#逐行统计关键字行数,并将关键字所在行存放在新的文件中 keyword = "INFO" b = open("C:\\Users\\xxx\\Documents\\new ...
- angularJS遇到的坑
最近在用angularjs做一些东西,由于学艺不精,对angularjs了解不够,导致经常会不小心掉进一些自己挖的坑里(⊙_⊙),在这里记下来,谨防又踩. 1.angularjs ng-show no ...