在刚学习MMX指令集的时候,我最大的疑惑便是它的意义,如果只是起到一个函数的作用,那么势必会拖慢汇编的运算效率,但通过实验发现,它不仅没有降低效率,反而比手写这段过程的执行效率要高。
下面通过一个实例来验证其运算效率:
(一)双声道数据的存储
#define short s16
#define int s32
用C来实现:
void mix_sample_c(s16* left, s16* right, s16* dest, s32 cnt)
{
int k;
for (k = 0; k < cnt; k++)
{
dest[k * 2] = left[k];
dest[k * 2 + 1] = right[k];
}
}
用通常思路的汇编来实现:
void mix_sample_asm(s16* left, s16* right, s16* dest, s32 cnt)
{
__asm
{
mov eax, left;
mov edx, right;
mov edi, dest;
s:movd mm0, [eax];
movd mm1, [edx];
pslld mm0, 16;
psrld mm0, 16;
pslld mm1, 16;
por mm0, mm1;
movd[edi], mm0;
add esi, 2;
add edi, 2;
add ebx, 4;
dec cnt
jnz s
emms;
}
}
用mmx的解包来实现:
void mix_sample_mmx(s16* left, s16* right, s16* dest, s32 cnt)
{
__asm
{
mov eax, left
mov edx, right
mov edi, dest
shr cnt, 3
l:
movq mm0, [eax]
movq mm1, [edx]
movq mm2, [eax + 4 * 2]
movq mm3, [edx + 4 * 2]
movq mm4, mm0
movq mm5, mm2
punpcklwd mm0, mm1
punpckhwd mm4, mm1
punpcklwd mm2, mm3
punpckhwd mm5, mm3
movq [edi], mm0
movq [edi + 4 * 2], mm4
movq [edi + 8 * 2], mm2
movq [edi + 12 * 2], mm5
add eax, 8 * 2
add edx, 8 * 2
add edi, 16 * 2
dec cnt
jnz l
emms
}
}
从代码量上来看,第三个的语句量要大很多,但要注意,在该方法中cnt右移了3位,也就是除以8,通过低位解包punpcklwd与高位解包punpckrwd一次循环就可以实现left[0]-left[7]与right[0]-right[7]对dest的赋值。
我们对上面三种方法进行测试,分别用COUNT为4096的left与right来对dest进行赋值,循环10000次,来输出运算时间:
可以看出,mmx的运算时间要比直接书写C短近10倍,在多媒体解码及编码的运用上,汇编语言及MMX的重要性不言而喻