PC平台的SIMD支持检测
如果我们希望在用SIMD来提升程序处理的性能,首先需要做的就是检测程序所运行的平台是否支持相应的SIMD扩展。平台对SIMD扩展分为两部分的支持:
- CPU对SIMD扩展的支持。SIMD扩展是随着CPU的发展不断改进的,CPU为SIMD扩展提供了硬件上的最基本支持。
- 操作系统对SIMD扩展的支持。目前PC上运行的基本都是多任务操作系统,也就是会“同时”运行着多个程序,这些程序依靠操作系统进行任务调度以使得多个程序看起来是在同时运行,在进行任务调度时需要进行程序上下文的切换,其中就包括寄存器内容的保存与恢复。操作系统对SIMD扩展的支持总的来说主要是在任务上下文切换时,对该SIMD扩展所使用的寄存器的保存与恢复。
CPU Identification
检查平台对SIMD扩展的支持,必不可少的就是指令CPUID。CPUID即CPU Identification,通过该指令能获取到CPU相关的各种信息,其中包括CPU制造商、CPU版本、CPU串号、对各种扩展的支持、Cache相关信息等等。
如果EFLAGS寄存器的ID flag(bit 21)能被置1或者置零的话,则表明能使用CPUID指令。CPUID没有任何操作数,不过CPUID却是一个功能性的指令,有输入以及输出。
- 输入用的寄存器为EAX(有时也会用到ECX作为扩展输入),用于指定CPUID的功能。在执行CPUID指令前需要往EAX寄存器写入相应的值。
- 输出用的寄存器为EAX、EBX、ECX、EDX共四个。在CPUID指令执行后可以从这四个寄存器中获取到所需要的信息。
如下所示为CPUID的一些基本功能
| Initial EAX Value |
Information Provided about the Processor | ||||||||||||||||||
| Basic CPUID Information | |||||||||||||||||||
| 00H |
|
||||||||||||||||||
| 01H |
|
||||||||||||||||||
| 02H |
|
||||||||||||||||||
| 03H |
|
||||||||||||||||||
| ... | |||||||||||||||||||
检查CPU对SIMD扩展的支持
通过指令CPUID可以检测CPU对SIMD扩展的支持。在输入为EAX=01H的情况下执行CPUID,可以使得ECX以及EDX返回如下信息:


其中与SIMD扩展硬件支持的相关bit如下,当相应的bit为1时表示支持该扩展:
| Register | Bit | Feature |
| ECX | 0 | SSE3 |
| 9 | SSSE3 | |
| 12 | FMA | |
| 19 | SSE4.1 | |
| 20 | SSE4.2 | |
| 25 | AES | |
| 28 | AVX | |
| EDX | 23 | MMX |
| 25 | SSE | |
| 26 | SSE2 |
在输入为EAX=07H的情况下执行CPUID,可以通过返回的寄存器EBX上的bit5以及bit16分别检测CPU对AVX2以及AVX512的支持状况。
| Register | Bit | Feature |
| EBX | 5 | AVX2 |
| 16 | AVX512 |
检查操作系统对SIMD扩展的支持
程序通过访问寄存器XCR0(eXterned Control Register)可以得到操作系统对SIMD扩展的支持信息。该寄存器通过XSETBV进行设置,通过XGETBV进行读取。
回顾上一小节,可以看到EAX=01H CPUID.ECX的26、27bit分别为XSAVE以及OSXSAVE。其中XSAVE为1则表示存在XCR0寄存器,并且可以通过XSETBV以及XGETBV访问该寄存器。对操作系统来说,会先查看处理器是否支持XSAVE,如果支持,则会根据操作系统自身的实现情况去设置XCR0寄存器。不过,操作系统与一般的程序有不同的权限,操作系统可以通过设置CR4寄存器的bit8(CR4.OSXSAVE)来控制一般程序对XCR0的访问权限,CPUID得到的OSXSAVE(bit27)表示的就是操作系统是否设置了允许一般程序去访问XCR0寄存器,我们一般的程序只需要去判断这一个bit就知道是否能访问XCR0。
| Register | Bit | Feature | Description |
| ECX | 26 | XSAVE | 为1则表明该处理器支持XSAVE/XRSTOR,支持扩展state,支持XSETBV/XGETBV之类,支持XCR0寄存器 |
| 27 | OSXSAVE | 为1则表明操作系统允许一般程序通过XSETBV/SGETBV访问XCR0寄存器,允许一般程序通过XSAVE/XRSTOR访问扩展state |
如果OSXSAVE=1,则可以通过XGETBV指令访问XCR0寄存器,得到系统对SIMD扩展的支持信息。指令XGETBV同样也没有任何的操作数,不过也存在输入与输出。其中输入为ECX,用于指定XCR寄存器,一般只有XCR0,即ECX=0。输出有64bit,保存于EDX:EAX。
XGETBV的输出,即返回值的各个bit有如下指示:

| Register | Bit | Feature | Description |
| EAX | 0 | MMX/FPU | 这个bit必为1,表明操作系统支持MMX以及ST寄存器 |
| 1 | SSE | 为1则表明操作系统支持XMM寄存器,32位时为XMM0~XMM7,64位时为XMM0~XMM15 | |
| 2 | AVX | 为1则表明操作系统支持YMM寄存器,32位时为YMM0~YMM7,64位时为YMM0~YMM15 | |
| 6 | ZMM_Hi265 | 为1则表明操作系统支持ZMM寄存器,32位时为ZMM0~ZMM7,64位时为ZMM0~ZMM15 | |
| 7 | Hi16_ZMM | 为1则表明如果CPU工作在64位模式,则操作系统支持ZMM16~ZMM31 |
总结
查看平台对SIMD扩展的支持需要分别检查处理器以及操作系统对SIMD扩展的支持。
- 处理器:调用EAX=1 CPUID,然后查看所返回的ECX或EDX寄存器相应的bit。
- 操作系统:调用EAX=1 CPUID,然后查看ECX.OSXSAVE(bit27),如果为1则调用XGETBV去获取XCR0,最后查看返回值EAX上相应的bit。
GCC:
#include <stdio.h>
inline static void cpuid (unsigned int output[4], unsigned int EAX, unsigned int ECX) {
unsigned int a, b, c, d;
__asm("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(EAX),"c"(ECX) : );
output[0] = a;
output[1] = b;
output[2] = c;
output[3] = d;
}
inline static unsigned int xgetbv (unsigned int ECX) {
unsigned int ret = 0;
__asm("xgetbv" : "=a"(ret) : "c"(ECX) : );
return ret;
}
int main(){
unsigned int CPUInfo[4] = {0}, ECX = 0, EDX = 0, XCR0_EAX = 0;
cpuid(CPUInfo, 1, 0);
ECX = CPUInfo[2];
EDX = CPUInfo[3];
if(EDX & 0x00800000)
printf("CPU Support MMX\n");
if(EDX & 0x02000000)
printf("CPU Support SSE\n");
if(EDX & 0x04000000)
printf("CPU Support SSE2\n");
if(ECX & 1)
printf("CPU Support SSE3\n");
if(ECX & 0x00000200)
printf("CPU Support SSSE3\n");
if(ECX & 0x00080000)
printf("CPU Support SSE4.1\n");
if(ECX & 0x00100000)
printf("CPU Support SSE4.2\n");
if(ECX & 0x02000000)
printf("CPU Support AES\n");
if(ECX & 0x10000000)
printf("CPU Support AVX\n");
if(ECX & 0x08000000)
printf("OS Support XSAVE\n");
else{
printf("OS not Support XSAVE, OS not Support SIMD\n");
return -1;
}
XCR0_EAX = xgetbv(0);
if(XCR0_EAX & 0x00000002)
printf("OS Support SSE/SSE2/SSE3/SSE4\n");
if(XCR0_EAX & 0x00000004)
printf("OS Support AVX\n");
if(XCR0_EAX & 0x00000040)
printf("OS Support AVX-512\n");
printf("ECX=%x, EDX=%x, XCR0_EAX=%x\n", ECX, EDX, XCR0_EAX);
return 0;
}
YASM:
global SIMD_Support ;this code just check SSE3 support
;bit0:SSE3, bit27:OSXSAVE
%define CPU_SUPPORT_CONST_ECX 0x08000001
;bit23:MMX, bit25:SSE, bit26:SSE2
%define CPU_SUPPORT_CONST_EDX 0x06800000 ;bit2:XMM
%define OS_SUPPORT_CONST 2 SIMD_Support:
;processor supports
mov eax, 1
cpuid
and ecx, CPU_SUPPORT_CONST_ECX
cmp ecx, CPU_SUPPORT_CONST_ECX
jne not_supported
and edx, CPU_SUPPORT_CONST_EDX
cmp edx, CPU_SUPPORT_CONST_EDX
jne not_supported ;OS supports
mov ecx, 0
XGETBV; result in EDX:EAX
and eax, OS_SUPPORT_CONST
cmp eax, OS_SUPPORT_CONST
jne not_supported mov eax, 0 ; return 0
ret not_supported:
mov eax, -1 ; return -1
ret
Reference:
Intel 64 and IA-32 Architectures Software Developer's Manual
PC平台的SIMD支持检测的更多相关文章
- PC平台主要SIMD扩展发展简史
Single Instruction Multiple Data,简称SIMD.SIMD描述的是微处理器中单条指令能完成对数据的并行处理.SIMD所使用的是特殊的寄存器,一个寄存器上存储有多个数据,在 ...
- PC平台在Unity3D中播放硬盘ogg,mp3,wav文件
Unity3D PC平台本身是支持直接用www读取本地ogg,wav的,但是并不能读取byte[],字节数组格式,这对用习惯了bass,fmod的人来说有点不方便. 搜了一圈发现了一个C#的音频库叫N ...
- 1、大部分社交平台接口不支持https协议。
参考文献来自:http://wiki.mob.com/ios9-%E5%AF%B9sharesdk%E7%9A%84%E5%BD%B1%E5%93%8D%EF%BC%88%E9%80%82%E9%85 ...
- 20165309 《网络对抗技术》实验一:PC平台逆向破解
20165309 <网络对抗技术>实验一:PC平台逆向破解 目录 实践目标 基础知识 实验原理.内容及步骤 问题与解决 实验收获 一.实践目标 本次实践的对象是一个名为pwn1的linux ...
- 1个多商户、多平台版 微信小程序(多商户、多平台版),影城行业、影业连锁 多商户、多平台版微信小程序。(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本)
1个 影城行业 微信小程序(多商户.多平台版), 影业连锁 多商户.多平台版微信小程序.(基于多平台版,支持在业务上 可给 每个单独影城 分发定制单独的小程序版本) 资讯QQ: 876635409 ...
- 20145325张梓靖 《网络对抗技术》 PC平台逆向破解
20145325张梓靖 <网络对抗技术> PC平台逆向破解 学习任务 shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并 ...
- 2017-2018 Exp1 PC平台逆向破解 20155214
目录 Exp1 PC平台逆向破解 实验内容 知识点 官方源 中科大源 上海交大的源 新加坡源 debain源 debian安全更新源 163源的地址 阿里云kali源 启发 评论 Exp1 PC平台逆 ...
- 20155233 Exp1 PC平台逆向破解(5)M
Exp1 PC平台逆向破解(5)M 实践一 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 步骤 1.cp pwn1 pwn20155233拷贝pwn1文件,命名为pwn201 ...
- 20145331魏澍琛 《网络对抗技术》 PC平台逆向破解
20145331魏澍琛 <网络对抗技术> PC平台逆向破解 学习任务 1.shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中 ...
随机推荐
- vue-cli sass安装
一.安装对应依赖node模块: npm install node-sass --save-dev npm install sass-loader --save-dev 二.打开webpack.base ...
- Burp Suite学习之Intruder的4种攻击模式
burp suit的intruder攻击共有四种模式,如图所示,下面分别讲讲这四种模式的使用方法和场景. 一 .Sniper模式 Sniper模式使用一组payload集合,它一次只使用一个paylo ...
- 无预挖无ICO-潜力币XDAG最强攻略
更新下XDAG上交易所了,当时看好这个币才推荐的,那时场外才2毛不到,现在涨到9毛一个了... https://www.coinbat.com/trade/panel/xdag... VBitEX [ ...
- RNG牛掰!
2018-05-21 RNG牛掰!Uzi圆梦! 不说了,先去哭了! 2018-07-08 洲际赛后更新,RNG依然牛逼! 2018-08-30 亚运后后更新,UZI加油! 2018-10-22 继续加 ...
- 52abp框架asp.net core & Angular快速开发实战视频教程
课程标题 52abp框架asp.net core & Angular全栈开发实战视频课程 课程简介 从零开始学 52ABP企业开发框架,企业项目是如何开发和技术选型,代码如何管理,团队协同开发 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...
- c++继承实例
#include <iostream> #include <vector> #include <string> using namespace std; class ...
- Pytorch 初识
文章目录 一个简单的回归网络的例子 再来一个例子 官方教程上图片识别的例子 import torch import torch.nn as nn import torch.nn.functional ...
- c#中用sql存储过程
string connstr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionStri ...
- 软件工程(FZU2015) 赛季得分榜,第9回合
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...