程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> MMX指令集在C++中的使用

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

編輯:關於VC++

上次在《關於內聯匯編的幾個技巧》一文中只是簡單地介紹了如何在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位寄存器。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved