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实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中 ...
随机推荐
- centos 7 java1.8安装
java安装 检查版本信息,如果版本小于1.8,执行以下命令 java -version java version "1.8.0_144"Java(TM) SE Runtime E ...
- 一次linux服务器黑客入侵后处理
场景: 周一上班centos服务器ssh不可用,web和数据库等应用不响应.好在vnc可以登录 使用last命令查询,2号之前的登录信息已被清空,并且sshd文件在周六晚上被修改,周日晚上2点服务器 ...
- 页面添加iconfont字体-[超详细]-支持彩色
第一步: 去矢量图官网注册一下,获取小图标(字体) 的来源 (也可以是其他类似的网站)这里以 阿里妈妈矢量图 官网为例,因为图标丰富,方便使用. 注册请点:https://www.iconfont.c ...
- 十四、怎么获取data-id中的值
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Really Big Numbers CodeForces - 817C (数学规律+二分)
C. Really Big Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...
- 为什么HashMap初始大小为16,为什么加载因子大小为0.75,这两个值的选取有什么特点?
先看HashMap的定义: public class HashMap<K,V>extends AbstractMap<K,V>implements Map<K,V> ...
- Vue使用的一些实例
1.实现歌曲的点击切换. <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- js this的含义以及讲解
this关键字是一个非常重要的语法点.毫不夸张地说,不理解它的含义,大部分开发任务都无法完成. 首先,this总是返回一个对象,简单说,就是返回属性或方法“当前”所在的对象. 下面来两个例子来让大家更 ...
- 902. Kth Smallest Element in a BST
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. You ...
- spring bean之间的关系:继承,依赖,注入
一 继承 spring中多个bean之间的继承关系,和面向对象中的继承关系类似,直接看代码. 先定义一个Person类 package com.demo.spring.entity; /** * @a ...