2008年(909)
分类:
2008-05-06 21:27:31
下载本文示例源代码
上次在《关于内联汇编的几个技巧》一文中只是简单地介绍了如何在C 中使用内联汇编,这一次先对上一次的文章作一补充,然后介绍如何使用MMX指令。
一、 内联汇编的一般原则:
1、 自由使用通用寄存器;(EAX,EBX,ECX和EDX)
2、 其它寄存器利用堆栈保留,使用,最后恢复;
一般的像下面这样:
__asm{ push ebp push esp ……….//使用EBP和ESP pop esp pop ebp }二、 内联汇编__asm可以单独使用:
__asm mov eax,anyval1 __asm mov ebx,anyval2三、 函数返回值可以直接放到eax中,可以不理会警告
int anyfun(……/*anyparm*/) { int irtn; //函数返回值 …… //函数语句 __asm mov eax,irtn //代替return irtn;但编译器会发出警告,可以不理它 }四、 内联汇编不区分大小写,语法同普通汇编
__asm{ mov eax,ebx MOV EAX,EBX //同上一句 }注意:C 的变量还是区分大小写的
__asm{ …..MMX 语句 EMMS //清空状态 }以上是所有的MMX指令,你可以测试使用其中的指令,他的工作原理就是单指令,多数据
2、 使用MMX指令集的注意事项
由于在CPU内部,FPU寄存器和MMX寄存器是同一组寄存器,所以在同时引用上面寄存器时要注意正确的状态转换,具体做法以后在探讨。你只要先记住不能简单的混合以上两种指令集即可。
每次调用之前要先检测cpu是否支持MMX指令集,以免发生异常。具体做法看下列示例:
mov EAX, 1 ; request for feature flags CPUID ; 0Fh, 0A2h CPUID instruction test EDX, 00800000h ; Is IA MMX technology bit (Bit 23 of EDX) ; in feature flags set? jnz MMX_Technology_Found这段代码来自Intel的参考手册,所以你可以放心的使用。
__int8 i8_a[2][16]; //字节操作数,两组,每组16个 __int16 i16_a[8]; //字操作数 __int32 i32_a[4]; __int64 i64_a[2]; i64_a[0]=0; i64_a[1]=0; i32_a[0]=1000; i32_a[1]=1000; i32_a[2]=3; i32_a[3]=4; i16_a[0]=10; i16_a[1]=20; i16_a[2]=30; i16_a[3]=40; i16_a[4]=50; i16_a[5]=60; i16_a[6]=70; i16_a[7]=80; i8_a[0][0]=1; i8_a[0][1]=1; i8_a[0][2]=1; i8_a[0][3]=1; i8_a[0][4]=1; i8_a[0][5]=1; i8_a[0][6]=1; i8_a[0][7]=1; i8_a[0][8]=1; i8_a[0][9]=1; i8_a[0][10]=1; i8_a[0][11]=1; i8_a[0][12]=1; i8_a[0][13]=1; i8_a[0][14]=1; i8_a[0][15]=1; i8_a[1][0]=2; i8_a[1][1]=2; i8_a[1][2]=2; i8_a[1][3]=2; i8_a[1][4]=2; i8_a[1][5]=2; i8_a[1][6]=2; i8_a[1][7]=2; i8_a[1][8]=2; i8_a[1][9]=2; i8_a[1][10]=2; i8_a[1][11]=2; i8_a[1][12]=2; i8_a[1][13]=2; i8_a[1][14]=2; i8_a[1][15]=2; __asm{ movq mm1,[i64_a] movq mm2,[i64_a] movq mm2, [i32_a 8] psubd mm2, [i32_a] movq [i32_a],mm2 movq mm1,[i16_a] paddsw mm1,[i16_a 8] movq [i16_a],mm1 movq mm1,[i8_a] movq mm2,[i8_a 8] paddb mm1,[i8_a 16] paddb mm2,[i8_a 24] movq [i8_a],mm1 movq [i8_a 8],mm2 emms //最后清除MMX状态寄存器,正确返回给系统 }