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 允许 ...
随机推荐
- (转)Html邮件CSS指南
转载地址:http://www.maildesign.cn/archives/937 分享来自Campaignmonitor非常实用的Html邮件中CSS的支持文档! 他们总结的Html邮件的CSS指 ...
- linux-centos6①
- beauifulsoup模块的介绍
01 爬虫基础知识介绍 相关库:1.requests,re 2.BeautifulSoup 3.hackhttp 使用requests发起get,post请求,获取状态码,内容: 使用re匹 ...
- Qt-网络与通信-TCP版本聊天程序
代码在公司,考不出来,智能用书里自带的例子来写了. 不过这个TCP版本的程序并没有出来书上的效果,具体问题出在哪里还没有找到,运行书里自带的代码也是这样. 另外发现一个问题 Qt5.8.0VS版本对中 ...
- 第一模块·开发基础-第1章 Python基础语法
Python开发工具课前预习 01 Python全栈开发课程介绍1 02 Python全栈开发课程介绍2 03 Python全栈开发课程介绍3 04 编程语言介绍(一) 05 编程语言介绍(二)机器语 ...
- ajax 个人理解 学习笔记
W:Ajax Q:异步网络请求.无刷新请求数据. W:ajax的实现流程如下: Q: 创建XHR对象 调用open()方法,创建请求 调用send()方法,发送请求 捕获请求状态,判断请求结果 获取数 ...
- ffmpeg接收rtsp流问题
项目使用mingw环境g++5.3,C++调用ffmpeg接收rtsp流,再通过C#显示.结构上是C#调用C++的so文件,读取得到的视频帧(RGB888格式),通过图片控件显示. 一开始是使用ope ...
- 在linux下PHP和Mysql环境搞事情
研发部门同事开发了一个接口管理辅助工具Shepherd,要求搭建在内网环境中,遇到点小问题记一下. 将开发的文件上传只web目录下,更改数据库ip,可以正常打开 登陆用户信息,此时需要连接数据库来验证 ...
- iconFont 阿里巴巴矢量图标使用方法
挑选图标的过程(共6步) 进入网站:Iconfont网址:http://www.iconfont.cn 点击网站上方的“官方图标库”,选择自己喜欢的图标.在这里我选择天猫的图标库. 选择好自己喜欢的图 ...
- 关于ES6-{块级作用域 let const 解构赋值 数组 字符串 函数的扩展 箭头函数}
关于ES6 块级作用域 任何一对花括号({})中的语句集都属于一个块,在块中声明的变量在代码块外都是不可访问的,称之为块级作用域,ES5以前没有块级作用域 let let 是ES6新增的声明变量的一种 ...