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实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中 ...
随机推荐
- Netty入门(三)之web服务器
Netty入门(三)之web服务器 阅读前请参考 Netty入门(一)之webSocket聊天室 Netty入门(二)之PC聊天室 有了前两篇的使用基础,学习本文也很简单!只需要在前两文的基础上稍微改 ...
- eclipse maven 常见问题解决方案
一.eclipse集成与设置 传送门:http://www.cnblogs.com/tweet/p/7602044.html 二.创建maven webapp工程,报错 报错信息:Could not ...
- 关于NETCORE中的捆绑与最小化 以及与CDN连用
参考文档:MSDN Bundling and minification in ASP.NET Core 细说ASP.NET Core静态文件的缓存方式
- vue-area-linkage Vue省市区三级列表联动插件使用
官方演示地址 // v5及之后的版本 数据依赖于area_data npm i --save vue-area-linkage area-data import Vue from 'vue'; imp ...
- 学习用Node.js和Elasticsearch构建搜索引擎(2):一些检索命令
1.Elasticsearch搜索数据有两种方式. 一种方式是通过REST请求URI,发送搜索参数: 另一种是通过REST请求体,发送搜索参数.而请求体允许你包含更容易表达和可阅读的JSON格式.这个 ...
- Python-爬虫小例子-55
import re from urllib.request import urlopen def getPage(url): response = urlopen(url) return respon ...
- PHP实用代码片段(三)
1. 目录清单 使用下面的 PHP 代码片段可以在一个目录中列出所有文件和文件夹. function list_files($dir) { if(is_dir($dir)) { if($handle ...
- FreeBSD常用操作
导读 最近遇到一些FreeBSD的故障,在这种操作系统上我们平时用的一些命令无法执行,FreeBSD的一些配置文件也和其他很多Linux系统不一样.为了方便以后查阅,我特别整理了这篇文档. 1. 网络 ...
- MySQL 遇到的问题以及解决方案
Problem: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysq ...
- 【学习总结】Master课程 之 虚拟化与云计算
Section 1- Cloud Computing Introduction-云计算介绍 1-What can Cloud Computing do? - 云计算可以做什么? 服务模式:美国国家标准 ...