目录
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: