登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
 内容搜索 网页 下载 源代码
热点文章
  SSE 介紹
  浮点数到整数的快速转换
  基于SSE指令集的程序设计简介
  CPU 的 cache 和 latency
  关键字 对齐 内存对齐
  INTEL 体系结构 MMX™ ..
  在非MFC程序中使用调试宏 AS..
  Microsoft Visual C++ 浮点优..
  INTEL X86 体系 32 位汇编语..
  加速&优化技术
  加快程序运行速度的技巧
  VC代码的编写和调试
本站原创
您现在的位置:立华软件园->游戏开发->程序设计->优化调试
INTEL 体系结构 MMX™ 技术开发者手册
发表日期:2006-08-28作者:[转贴] 出处:  

从今天起开始介绍一下MMX指令集。

MMX技术大家肯定是如雷贯耳,也不用我多废话了。总之,它是SIMD(单指令多数据)技术的一个最简单的部分,它只能对整数(BYTE、WORD、DWORD、QWORD)进行操作,而且提供的指令也有限,不象Intel原来的指令集那么复杂。但是我们可敬的雷锋叔叔不是说过“要把有限的生命投入到无限的为人民服务之中去”么?我们这里也是一样,要把有限的指令应用到无限的计算方法当中去。简单有限的指令组合起来,一样可以完成近乎无限的功能。不信可以去Intel的网站(http://www.intel.com/software/idap/processor/ia32/mmx/)看看,那里有非常多的应用MMX技术来优化了的算法,包罗了图像、图形、音频、通讯、信号处理等几乎所有现在比较流行的技术。当然SSE和SSE2又更进了一步,不过我们现在是讨论MMX,先把这个搞定对于理解其他的SIMD技术肯定是大有帮助。

好了,废话少说,开始进入正题。
先来讲一下MMX寄存器。MMX寄存器实际上用的就是浮点寄存器(就是原来的ST0、……、ST7)的低64Bit(至少一直到PII还是这样,PIII是不是这样我就不知道了),分别被命名为MM0、MM1、……、MM7,每个寄存器都可以被看作是8个BYTE,4个WORD、2个DWORD或1个QWORD,具体以什么为单位取决于所用的指令。MMX指令可以把这几个数据在一条指令里同时操作,而且相互间各不相干,例如下图所示:
 ┌───┬───┬───┬───┐
 │ A1 │ A2 │ A3  │ A4  │
 └───┴───┴───┴───┘
 ┌───┬───┬───┬───┐
 │ B1 │ B2 │ B3  │ B4  │
 +└───┴───┴───┴───┘
 ──────────────────
 ┌───┬───┬───┬───┐
 │A1+B1 │A2+B2 │A3+B3 │A4+B4 │
 └───┴───┴───┴───┘
这对数据密集型的计算(比如图像处理)是个相当大的喜讯。但是因为它实际使用的是浮点寄存器,所以不能和浮点运算同时执行(占了人家的房子当然不好意思了),要执行浮点指令前必须执行一条EMMS指令,通知CPU“我的租期到了,现在该把房子还给你了”。这么一条指令也是要花时钟周期的(可能还绝对不止一个时钟周期),要是频繁的切换MMX状态和浮点状态,从MMX技术获得的这么点利润就又全陪进去了。所以在写代码的时候要注意,务必使MMX指令的运算和浮点运算分开来,个人管个人,免得一个房子两个人挤。

下面介绍MMX指令。
在MMX指令集里加入了几个原来Intel指令集里没有(当然没有了,我指的是没有类似的运算指令)的非常好用的指令,我以前搞过图像处理,最能理解这几个指令的好处,就先从这几个指令讲起。

1.饱和运算
所谓饱和运算,就是当运算结果大于一个上限或小于一个下限时,结果就等于上限或是下限。例如:BYTE运算,最大值是255,0xF1+0x35应该是等于0x26,但由于结果大于255,那么饱和运算的结果就是0xFF。在图像处理里经常有(比如说增加亮度)两种灰度值运算后要判断只是否大于255或小于0,根据结果再取255或0,又是if又是什么的。现在只要一条指令就OK了。
这几条指令分别是:

PADDS[B,W] 饱和有符号数加[byte, word]
PADDUS[B,W] 饱和无符号数加[byte, word]
PSUBS[B,W] 饱和有符号数减[byte, word]
PSUBUS[B,W] 饱和无符号数减[byte, word]


是不是很方便啊!(有符号数就是有正有负,一个BYTE就是-128~127;无符号数就是都是正的,一个BYTE就是0~255)
注:PADDS[B,W]的意思就是PADDSB和PADDSW的简写,以下都将这样写。

2.向量点乘指令
什么是向量点乘我想不用我说了吧,学过高数的都该知道。这条指令的格式如下:

PMADDWD 向量点乘运算(word)

其实际操作为:

┌───┬───┬───┬───┐
│  A1  │  A2  │  A3  │  A4  │
└───┴───┴───┴───┘
┌───┬───┬───┬───┐
│  B1  │  B2  │  B3  │  B4  │
└───┴───┴───┴───┘ PMADDWD
──────────────────────
┌───────┬───────┐
│  A1*B1+A2*B2 │  A3*B3+A4*B4 │
└───────┴───────┘

这条指令的用处不要我说了,高数里有好多这种运算。我只是感叹,这么好用的指令为什么Intel不早点想出来呢?

3.串比较指令
这类指令有两个

PCMPEQ[B,W,D] 串等于比较(byte,word,dword)
PCMPGT[B,W,D] 串大于比较(byte,word,dword)

举个例子说明实际操作

┌───┬───┬───┬───┐
│ 0xF0 │ 0xA2 │ 0x24 │ 0x75 │
└───┴───┴───┴───┘
┌───┬───┬───┬───┐
│ 0xF0 │ 0x2C │ 0x24 │ 0x54 │
└───┴───┴───┴───┘PCMPEQ
─────────────────────
┌───┬───┬───┬───┐
│ 0xFF │ 0x00 │ 0xFF │ 0x00 │
└───┴───┴───┴───┘

┌───┬───┬───┬───┐
│ 100  │  70  │   6  │  18  │
└───┴───┴───┴───┘
┌───┬───┬───┬───┐
│  40  │  120 │   5  │  26  │
└───┴───┴───┴───┘PCMPGT
─────────────────────
┌───┬───┬───┬───┐
│ 0xFF │ 0x00 │ 0xFF │ 0x00 │
└───┴───┴───┴───┘

看明白了?结果为全1,即说明比较结果为TRUE;结果为全0,说明比较结果为FALSE。这条指令用在什么地方?字符串快速比较(Intel网站上有源码,扬言速度提高50%)、模拟Color Key(具体怎么实现不在本文讨论范围之内,自己想一想,我以后可能会介绍一下)等等好多方面。

接下来的指令就比较普通了,但还是有非常大的便宜可以占的。

4.数据传输

MOV[D,Q] 数据传输(dword,qword)

MOVD就是传32个Bit(传到MMX寄存器的低32Bit或只传输MMX寄存器的低32Bit),MOVQ就是传64个Bit,这条指令是可以在MMX寄存器、通用寄存器(就是EAX、ESI之类,但是这些寄存器只能用在MOVD里——一直到PIII都还是32Bit的通用寄存器嘛)和内存之间来回折腾的,没什么限制。

5.算术指令
这里的指令和普通的算术指令没有什么运算规则上的区别,只不过是在一条指令里同时处理几个数据而已。指令如下:
PADD[B,W,D] 无符号数加[byte,word,dword]
PADDS[B,W] 有符号数加[byte,word]
PSUB[B,W,D] 无符号数减[byte,word,dword]
PSUBS[B,W] 有符号数减[byte,word]
PMULHW 有符号数乘取高位[word]
PMULLW 有符号数乘取低位[word]

值的提一下的是那两个乘法指令,因为两个WORD相乘,结果是个DWORD,但在MMX指令里又要保持数据的一致性,不可能是交给它4个数据,运算完了就剩下2个数据了,于是Intel就搞了这么个方法,乘法嘛,要算两次,一次只把高位给你,另一次再把低位给你——怎么,不服气么?哼,我给了你这么多方便又好用的指令,才讹了你这么点儿时钟周期就不满意了?CPU是我做还是你做?哼,没话说了吧!——没办法,人家是老大,该怎样就怎样了。不过凡事要往两方面想,假如我们要判断两数是否同号,只要乘完了取高位就行了,低位嘛,在这儿用不上,随它怎么样了,而且还省了个寄存器。
这两条指令的实际操作如下(只写一条就行了):

┌───────┬───┬───┐
│      A1      │  …  │  …  │
└───────┴───┴───┘
┌───────┬───┬───┐
│      B1      │  …  │  …  │
└───────┴───┴───┘PMULHW
─────────────────────
┌───────┬───┬───┐
│HIWORD(A1*B1) │  …  │  …  │
└───────┴───┴───┘

但是大家发现没有,这里没有除法运算,也没有无符号数的乘法运算,不要急,PIII的SSE指令集里就有了,大家升级CPU啊!

6.逻辑指令
这些指令和原来我们学过的8086汇编里的逻辑指令完全相同(除了PANDN相当于原先的两个操作——与和非——的结合),只是把寄存器换成64位的而已。

PAND 按位与操作
PANDN 按位与后再取非操作
POR 按位或操作
PXOR 按位异或操作

7.移位指令
移位指令也不要我多说了,实际就是更方便(方便嘛当然就要有点儿限制了)的乘除法运算。但是却没有BYTE为单位的移位运算,不知道是为什么。

PSLL[W,D,Q] 逻辑左移[word,dword,qword]
PSRL[W,D,Q] 逻辑右移[word,dword,qword]
PSRA[W,D,Q] 算术右移[word,dword,qword]

再提一句,这条指令的源操作数(就是放在后面的那个)可以是个立即数,就像
PSLLW MM0, 2
这样,就是每个WORD左移2位。还有,当源操作数是MMX寄存器或是内存地址时,CPU是把它当成一个数来看的,注意了,不要以为还是当分开的数据看,对应的单元移位对应的位数(我曾经以为会是这样,但事实证明我是错的),那有这种美事?


8.数据转换指令

现在已经讲了绝大部分的MMX指令,大家看到了吧,每个指令前都有个“P”开头。这个“P”的意思就是——Packet,就是说每个寄存器里的数据都是个数据包,而不是一个数据。那么这些指令就是把这些数据打包或拆包(我不知该怎么下这个操作的定义)用的。这些指令的操作都有点儿怪异,倒需要详细说明一下。
PACKUSWB 有符号数WORD带饱和压缩成无符号BYTE
PACKSS[WB,DW] 有符号数带饱和压缩成有符号数[word->byte,dword->word]
PUNPCKH[BW,WD,DQ] 交错放置两数的高位[byte->word,word->dword,dword->qword]
PUNPCKL[BW,WD,DQ] 交错放置两数的低位[byte->word,word->dword,dword->qword]

先说一下PACKUSWB。举个例子,PACKUSWB MM0, MM1,其实际操作为(图示为高位在左,低位在右),

┌───┬───┬───┬───┐    ┌───┬───┬───┬───┐
MM1│  A   │  B   │  C   │  D   │    │  E   │  F   │  G   │  H   │MM0
└───┴───┴───┴───┘    └───┴───┴───┴───┘
│                                                              │
└─────────────┐      ┌─────────────┘
│      │
┌─┬─┬─┬─┬─┬─┬─┬─┐
│A │B │C │D │E │F │G │H │MM0
└─┴─┴─┴─┴─┴─┴─┴─┘
不知道大家有没有看明白。大致意思就是:目的数紧缩到低位,源操作数紧缩到高位。另外,这个指令是带饱和操作的,就是说大于255的紧缩后就变成255,小于0的紧缩后就变成0。
PACKSS[WB,DW]的操作和PACKUSWB一样,不过多了个[DW],就是从DWORD紧缩成WORD。

再说一下拆包操作。名字虽然是UNPACK,实际好像不是PACK的逆操作,反倒有点怪,这个操作和乘法操作有一点点类似,也有高位和低位之分的。比如说:PUNPCKHBW MM0, MM1,其实际操作为:

┌─┬─┬─┬─┬─┬─┬─┬─┐    ┌─┬─┬─┬─┬─┬─┬─┬─┐
MM1│A1│B1│C1│D1│E1│F1│G1│H1│    │A2│B2│C2│D2│E2│F2│G2│H2│MM0
└─┴─┴─┴─┴─┴─┴─┴─┘    └─┴─┴─┴─┴─┴─┴─┴─┘
│                                                                  │
└──────────────┐      ┌──────────────┘
│      │
┌─┬─┬─┬─┬─┬─┬─┬─┐
│A1│A2│B1│B2│C1│C2│D1│D2│MM0
└─┴─┴─┴─┴─┴─┴─┴─┘
有了PACKUSWB作基础,大家应该看懂这个图示了吧。这明明不是什么拆包操作是吧!唉,我不过是为了讲究名称的匹配,再说它的指令助记符也写着是UNPACK嘛,不就是个名称,你又何必认真呢?PUNPCKL[BW,WD,DQ]的操作和PUNPCKH类似,就是把两个数的低位交错着放到目的数里。

OK,到此为止,MMX指令集简介正式结束,谢谢大家。


我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 INTEL 体系结构 MMX™ 技术开发者手册

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接

Copyright ©2001-2003 Allrights reserved
e_mail:站长:webmaster(at)lihuasoft.net
网站编程QQ群  
京ICP备05001064号

页面生成时间:0.00464