`
congfeng02
  • 浏览: 200034 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

MMX指令集在C++中的使用

阅读更多

MMX指令集在C++中的使用
作者:孙原

下载本文示例源代码

上次在《关于内联汇编的几个技巧》一文中只是简单地介绍了如何在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或_asm关键字,而不用标准C++的asm关键字(这个是微软说的)
以上只是一些关于内联汇编的补充,我将出一系列围绕内联汇编的文章,下面接着上一次的话题详细一点地讲一下MMX指令的调用

1、 MMX指令集简介

[数据传输指令]
movq //传输64位整数
movd //传输32位整数

[数据打包转换指令]
PACKSSWB //Pack words into bytes with signed saturation.
PACKSSDW //Pack doublewords into words with signed saturation.
PACKUSWB //Pack words into bytes with unsigned saturation.
PUNPCKHBW //Unpack high-order bytes.
PUNPCKHWD //Unpack high-order words.
PUNPCKHDQ //Unpack high-order doublewords.
PUNPCKLBW //Unpack low-order bytes.
PUNPCKLWD //Unpack low-order words.
PUNPCKLDQ //Unpack low-order doublewords.
注:这一组指令我没有具体用过,不知道是干什么的,请高手赐教!小弟先谢了!

[ 算术指令]
PADDB
PADDW
PADDD
PADDSB
PADDSW
PADDUSB
PADDUSW
PSUBB
PSUBW
PSUBD
PSUBSB
PSUBSW
PSUBUSB
PSUBUSW
PMULHW
PMULLW
PMADDWD

[ 比较指令]
PCMPEQB Compare packed bytes for equal.
PCMPEQW Compare packed words for equal.
PCMPEQD Compare packed doublewords for equal.
PCMPGTB Compare packed signed byte integers for greater than.
PCMPGTW Compare packed signed word integers for greater than.
PCMPGTD Compare packed signed doubleword integers for greater than.
这组指令用于成组比较数据

[ 位逻辑指令]
PAND Bitwise logical AND.
PANDN Bitwise logical AND NOT.
POR Bitwise logical OR.
PXOR Bitwise logical exclusive OR.
这组指令与AND,XOR基本相同,都是按位进行逻辑运算。

[ 移位和循环移位指令]
PSLLW //Shift packed words left logical.
PSLLD //Shift packed doublewords left logical.
PSLLQ //Shift packed quadword left logical.
PSRLW //Shift packed words right logical.
PSRLD //Shift packed doublewords right logical.
PSRLQ //Shift packed quadword right logical.
PSRAW //Shift packed words right arithmetic.
PSRAD //Shift packed doublewords right arithmetic.

[ 状态管理指令]
EMMS //Empty MMX state.
在VC中要求所有的MMX指令调用完毕后都要调用这个指令清空
例如:
__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的参考手册,所以你可以放心的使用。

3、 下面用一段示例代码来说明一下怎样用MMX指令
__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状态寄存器,正确返回给系统
	}

你可以通过设置断点,和watch的方法来观察寄存器以及变量的变化情况,这里只是引用了一部分的指令,那么最引人注意的是对i16_a、i8_a、以及i32_a数组的操作,我是随便对他们进行了算术运算,大家可以看到我加两组字节数组数据时只用了两条加指令,这是普通的指令集望尘莫及的。这就是单指令,多数据的魅力。同时你也可以看到对64位整数的操作也简单多了。但是要注意的是,MMX指令集里好像没有提供除法操作。所以你需借助算法来实现。另外要补充的是MMX寄存器是从MM0-MM7命名的一组64位寄存器。

孙原
2002.8.27于西安
分享到:
评论

相关推荐

    《mmx指令集在c++中的使用》

    提供的压缩包中的《MMX指令集在C++中的使用》配套代码,可能是作者为了展示如何在实际项目中应用 MMX 指令而编写的示例程序。用户可以通过阅读代码和运行程序来深入理解 MMX 技术在 C++ 中的应用。 总之,MMX 指令...

    《MMX指令集在C++中的使用》配套代码

    在《MMX指令集在C++中的使用》配套代码中,`mmxtest`这个文件很可能是包含了一个或多个演示如何在C++中使用MMX指令的实际程序。通过分析这个程序,可以更深入地了解MMX指令集在实际应用中的工作原理和效果。学习这...

    VC 使用MMX指令集的例子.rar

    这个"VC 使用MMX指令集的例子"压缩包中,包含了一个演示程序,用户可以通过点击“MMX”按钮来触发MMX指令的执行。这可能是通过编写一段C++代码实现的,这段代码使用了intrinsic函数,例如_mm_movemask_epi8、_mm_...

    用c++实现的mmx图像变换

    综上所述,"用C++实现的MMX图像变换"涉及到的知识点包括C++编程、图像处理理论、MMX指令集的使用、内存管理和对齐、性能优化以及多平台兼容性考虑。这些技能对于开发高效能的图像处理软件至关重要。

    intel汇编MMX/SSE指令集(a)

    MMX指令集首次在Pentium MMX处理器上实现,极大地提升了多媒体处理能力,是Intel在多媒体技术领域的一大里程碑。 SSE(Streaming SIMD Extensions),即流式SIMD扩展指令集,是MMX指令集的后续发展,进一步增强了...

    英特尔指令集

    英特尔指令集,全称为“Streaming SIMD Extensions”,简称SSE,是英特尔公司在 Pentium III 处理器中引入的一系列向量处理指令集,旨在提升处理器在处理多媒体和科学计算任务时的性能。SSE指令集是MMX(多媒体扩展...

    MMX+C++实现图片渐入渐出

    2. 分配内存空间,使用MMX指令集处理图像数据,更新Alpha通道。 3. 控制时间序列,逐渐调整Alpha值,生成一系列渐变帧。 4. 将处理后的图像数据保存为新的图像文件或显示在屏幕上。 5. 可能还需要考虑线程安全和多...

    MMX.rar_MMX programming_mmx_visual c

    可能涵盖了MMX指令集的介绍、如何在Visual C++中使用MMX指令、相关的编程技巧、示例代码以及可能的优化策略等内容。 **详细知识点:** 1. **MMX技术**:由英特尔公司在1996年推出,是CPU的一个扩展,增强了处理器...

    MMX.zip_MMX programming_mmx

    在编程中使用MMX技术,通常需要采用汇编语言进行低级操作,以充分利用其并行处理能力。然而,为了方便C++或C程序员,可以使用内联汇编或特殊的库函数来调用MMX指令。编程时需要注意以下几点: 1. **数据对齐**:由于...

    在Visual_C++中使用内联汇编

    ### 在Visual C++中使用内联汇编:深入解析与应用 #### 一、内联汇编概述 在计算机编程领域,特别是在C/C++中,内联汇编是一种特殊的编程技术,它允许开发者直接在高级语言中嵌入汇编语言代码。这种方式的主要优势...

    MMX汇编技术开发手册

    MMX指令集包括了数十条新的操作码,它们设计用来处理64位的向量数据,这些数据可以是单精度浮点数、双精度整数或者多个较小的数据单元。这些指令通常分为以下几类: 1. **数据加载和存储指令**:如`MOVQ`用于在MMX...

    mmx.rar_mmx_visual c

    为了有效地使用MMX,程序员需要了解MMX指令集,包括加载、存储、算术运算、逻辑运算以及比较操作等。同时,由于MMX操作可能涉及到处理器状态的改变,因此正确地管理上下文切换和同步也是必要的。在C++代码中,这通常...

    2022年在Visual C++中使用内联汇编C语言教程.docx

    Visual C++中使用内联汇编C语言教程 在 Visual C++ 中使用内联汇编 C 语言教程可以使开发者更方便地使用汇编语言编写函数、提高代码的执行速度、访问硬件等。内联汇编主要用于以下几种场景: 1. 使用汇编语言编写...

    MMX.zip_mmx_site:www.pudn.com

    开发人员需要了解如何编写利用MMX的汇编代码,或者在高级语言(如C/C++)中使用MMX相关的库函数,以充分利用硬件的并行处理能力。同时,需要注意的是,MMX指令集虽然强大,但在某些情况下可能需要与传统的x86指令集...

    大块内存拷贝源代码, 各种方法实现,包括mmx和sse指令

    在C/C++中,`memcpy`函数是最常用的内存拷贝工具,它接受三个参数:目标地址、源地址和要拷贝的字节数。其工作原理是逐个复制源内存区域的数据到目标内存区域。然而,对于大块内存的拷贝,这种基础方法可能会相对较...

    intel_intel指令集_intel_

    这些指令集为开发者提供了低级别的控制,使得他们能够编写高效的汇编语言程序,同时对高级编程语言(如C++、Java等)的编译器提供了必要的底层支持。 Intel指令集的发展经历了多个阶段,从最初的8086到现在的 ...

    在Visual C++中使用内联汇编

    在`__asm`块中,你可以使用完整的Intel 486指令集,包括MMX指令,但不支持所有MASM(Microsoft Assembler)的特性。例如,你不可以使用MASM的数据定义指示符如DB、DW等,也不能使用宏指示符和宏操作符。不过,`EVEN`...

    Intel的MMX技术文档(中英版)

    MMX指令集增加了57条新的SIMD(单指令多数据)指令,这些指令能够同时处理多个数据元素,如8位或16位整数,提高了处理多媒体数据的速度。通过将多个数据打包在一个寄存器中,MMX允许处理器一次性执行多个操作,显著...

    SSE指令集加速.docx

    - **代码示例**:实际编程中,SSE指令集通常通过内联汇编或C++库(如Intel Intrinsics Guide提供的函数)来实现。例如,使用`_mm_add_ps`函数可以轻松地对两个128位寄存器中的单精度浮点数组执行加法操作。 #### 四...

    SIMD指令集大全

    MMX指令集包括了对整数运算、逻辑运算和数据搬移的优化。 2. **SSE(Streaming SIMD Extensions)** - SSE是Intel在 Pentium III 中引入的增强版SIMD指令集,增加了更多浮点运算的支持。SSE包含4个128位的寄存器...

Global site tag (gtag.js) - Google Analytics