使用内联汇编获取在线OJ平台CPU的信息
目录
1.前置知识
2.LeetCode
3.LintCode
4.牛客
1.前置知识
获取CPU的信息的方法:
1.rax寄存器存储功能号
2.cpuid指令会根据不同的功能号执行不同的任务
1.功能号0: 获取厂商名,此时cpuid将厂商名的ASCII码一次返回到ebx、edx、ecx中,需要将它们存储的ASCII码拼起来,然后调用printf函数打印
2.功能号0x80000002: 获取CPU品牌名的前16个字节,此时cpuid将前16个字节的ASCII码一次返回到eax、ebx、ecx、edx中,需要将它们存储的ASCII码拼起来,然后调用printf函数打印
3.功能号0x80000003,获取CPU品牌名的中间16个字节
4.功能号0x80000004: 获取CPU品牌名的后16个字节
5.功能号0x40000000: 获取虚拟机
可以将寄存器中的返回值存储到栈中,手动添加\0,然后调用printf,注意需要手动平衡栈,例如以下例子:
"sub rsp,15;"
"mov rax,0;"//功能号0,获取厂商
"cpuid;"
"mov dword ptr [rsp],ebx;"
"mov dword ptr [rsp+4],edx;"
"mov dword ptr [rsp+8],ecx;"
"mov byte ptr [rsp+12],0x0;"//添加\0
"add rsp,15;"
根据printf函数打印字符串的System V ABI的调用约定:rdi存储字符串地址,eax清零表示没有浮点参数,之后方可call printf
"lea rdi,[rsp];"
"xor eax,eax;"//eax=0
"call printf;"
2.LeetCode
随便选一道题测试,这里选2235. 两整数相加
测试这个代码:
__attribute__((naked)) int sum(int num1, int num2)
{__asm__ volatile (".intel_syntax noprefix;""sub rsp,100;"//----------------------------"mov rax,0;"//功能号0,获取厂商"cpuid;""mov dword ptr [rsp],ebx;""mov dword ptr [rsp+4],edx;""mov dword ptr [rsp+8],ecx;""mov byte ptr [rsp+12],32;""mov rax,0x80000002;"//功能号0x80000002,获取CPU品牌名前16个字节"cpuid;""mov dword ptr [rsp+13],eax;""mov dword ptr [rsp+17],ebx;""mov dword ptr [rsp+21],ecx;""mov dword ptr [rsp+25],edx;""mov byte ptr [rsp+29],32;"//----------------------------"mov rax,0x80000003;"//功能号0x80000003,获取CPU品牌名中间16个字节"cpuid;""mov dword ptr [rsp+30],eax;""mov dword ptr [rsp+34],ebx;""mov dword ptr [rsp+38],ecx;""mov dword ptr [rsp+42],edx;""mov byte ptr [rsp+46],32;"//----------------------------"mov rax,0x80000004;"//功能号0x80000004,获取CPU品牌名后16个字节"cpuid;""mov dword ptr [rsp+47],eax;""mov dword ptr [rsp+51],ebx;""mov dword ptr [rsp+55],ecx;""mov dword ptr [rsp+59],edx;""mov byte ptr [rsp+60],32;"//----------------------------"mov rax,0x40000000;"//功能号0x40000000,获取虚拟机"cpuid;""mov dword ptr [rsp+61],ebx;""mov dword ptr [rsp+65],ecx;""mov dword ptr [rsp+79],edx;""mov byte ptr [rsp+73],32;""mov byte ptr [rsp+74],0x0;""lea rdi,[rsp];""mov eax,0;""call printf;""add rsp,100;"//---------------------------- "ret;"".att_syntax");
}
只看标准输出:
3.LintCode
随便选一道题测试,这里选3762 · 第一个 C 程序:打印 Hello World
调用上方的sum函数
int main()
{sum(1,2);return 0;
}
点击
只看输出数据:
4.牛客
点
只看stdout: