g++编译器内嵌汇编代码

最近要实现一个功能,获取系统的cpu信息,查阅网上的资料,如果是在VS20XX中可以用如下代码实现:

using namespace std;
 
//用来存储信息
DWORD deax, debx, decx, dedx;

static void ExeCPUID(DWORD veax)                  // 初始化CPU
{
    __asm
    {
        mov eax,veax
        cpuid
        mov deax,eax
        mov debx,ebx
        mov decx,ecx
        mov dedx,edx
    }
}

static float GetCPUFreq()                          // 获取CPU频率,单位: MHZ
{
    int start1,start2;
    _asm rdtsc
    _asm mov start1, eax
    Sleep(50);
    _asm rdtsc
    _asm mov start2, eax
    return ((start2 - start1) / 50) / (1000);
}

static string GetManID()                         // 获取制造商信息
{
    char ID[25];                                 // 存储制造商信息
    memset(ID, 0, sizeof(ID));                   // 先清空数组 ID
    ExeCPUID(0);                                 // 初始化
    memcpy(ID + 0, &debx, 4);                    // 制造商信息前四个字符复制到数组
    memcpy(ID + 4, &dedx, 4);                    // 中间四个
    memcpy(ID + 8, &decx, 4);                    // 最后四个

    return string(ID);
}

static string GetCPUType()
{
    const DWORD id = 0x80000002;                 // 从0x80000002开始,到0x80000004结束
    char CPUType[49];                            // 用来存储CPU型号信息
    memset(CPUType, 0, sizeof(CPUType));         // 初始化数组

    for(DWORD t = 0; t < 3; t++)
    {
        ExeCPUID(id + t);
        // 每次循环结束,保存信息到数组
        memcpy(CPUType + 16 * t + 0, &deax, 4);
        memcpy(CPUType + 16 * t + 4, &debx, 4);
        memcpy(CPUType + 16 * t + 8, &decx, 4);
        memcpy(CPUType + 16 * t + 12, &dedx, 4);
    } 

    return string(CPUType);
}



可是这段代码在VSCODE中却编译不过,提示__asm找不到,这是因为VSCODE用的编译器可能是g++,g++内嵌汇编语言的写法应该是:

DWORD deax, debx, decx, dedx;
int start1,start2;
static void ExeCPUID(DWORD veax)                  // 初始化CPU
{
    asm
    (
        "mov %eax,$veax\n\r"                     // 这里编译不过
        "cpuid\n\r"
        "mov $deax,%eax\n\r"
        "mov $debx,%ebx\n\r"
        "mov $decx,%ecx\n\r"
        "mov $dedx,%edx\n\r"
    );
}

static float GetCPUFreq()                          // 获取CPU频率,单位: MHZ
{
    asm(										   // 这asm指令执行并不生效 获取不到eax的值 
        "rdtsc\n\r"
        "mov $start1, %eax\n\r"
    );
    Sleep(50);
    asm( 										  // 这些asm指令执行并不生效 获取不到eax的值
        "rdtsc\n\r"
        "mov $start2, %eax\n\r"
    );
    return ((start2 - start1) / 50) / (1024);
}

注意点:参考(https://blog.csdn.net/ichuangxin/article/details/84275004)
1.std命名空间下,不能使用_asm_
2.寄存器要在前面加上%,多个命令时,命令以\n\r结尾,使得在将汇编代码插入目标文件时会换行
3.立即数前加$
4.不要定义局部变量,变量定义在函数外部,否则链接找不到?

可是即使这样还是编译不过,GetCPUFreq能编译过,但是执行结果不对
编译报错在cpuid的上一句指令,
报错内容为:Error: unsupported instruction `mov’
看起来不像是语法问题,而是和cpuid有关(待进一步确认)。

再次查询资料,如果要用g++,可以#include <cpuid.h>

#include <iostream>
#include <string>
#include <stdint.h>
#include <iostream>
#include <windows.h>
#include <cpuid.h>

static void cpuid(uint32_t func, uint32_t sub, uint32_t data[4]) 
{
    __cpuid_count(func, sub, data[0], data[1], data[2], data[3]);
}

static string GetManID()                         // 获取制造商信息
{
    uint32_t data[4];
    char ID[25];                                 // 存储制造商信息
    memset(ID, 0, sizeof(ID));                   // 先清空数组 ID
    cpuid(0, 0, data);                           // 初始化
    memcpy(ID + 0, &data[1], 4);                 // 制造商信息前四个字符复制到数组
    memcpy(ID + 4, &data[3], 4);                 // 中间四个
    memcpy(ID + 8, &data[2], 4);                 // 最后四个

    return string(ID);
}

static string GetCPUType()
{
    uint32_t data[4];
    char str[48];
    for(int i = 0; i < 3; ++i) 
    {
        cpuid(0x80000002 + i, 0, data);
        for(int j = 0; j < 4; ++j)
        {
            reinterpret_cast<uint32_t*>(str)[i * 4 + j] = data[j];
        }
    }

    return string(str);
}

inline int64_t timt()
{
    int64_t p; 
    int &a = *(((int*)&p) + 1);
    __asm__ __volatile__("rdtsc":"=a"(p),"=d"(a));
    return p;
}

static float GetCPUFreq()                // 获取CPU频率,单位: MHZ
{
    start1 = timt();
    Sleep(50);            				//  將線程掛起片刻 由於windows的Sleep函數有大約15毫秒的误差 所以其实这个函数算出来的频率并不准         
    start2 = timt();
    cout << "start1: " << start1 << " start2: " << start2 << endl;
    return ((start2 - start1) / 50) / (1000);  誤差,故以windows的精確計時為準
}

实现结果:(参考:https://blog.csdn.net/weixin_43731933/article/details/102734964)

在这里插入图片描述
在windows arm64平台中,intrin.h不支持cpuid

__MACHINEX86_X64(void __cpuid(int[4], int))
__MACHINEX86_X64(void __cpuidex(int[4], int, int))

可从注册表中得到cpu型号:


const int BUFSIZ= 65; // For easy adjustment of limits, if required
char answer[BUFSIZ] = "Error Reading CPU Name from Registry!", inBuffer[BUFSIZ] = "";
const char *csName = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
HKEY hKey;  DWORD gotType, gotSize = BUFSIZ;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, csName, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
    if (!RegQueryValueExA(hKey, "ProcessorNameString", nullptr, &gotType, (PBYTE)(inBuffer), &gotSize)) {
        if ((gotType == REG_SZ) && strlen(inBuffer)) strcpy(answer, inBuffer);
    }
    RegCloseKey(hKey);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值