更新时间:2023-12-24 16:19
MMX指令有8个64位寄存器(MM0~MM7),不过可惜都是借的FPU的, FPU原来有8个80位寄存器(st(0)~st(7)),现在用在了MMX 上,所以用之后要加上一条EMMS指令,用以复位。.
基本介绍
MMX寄存器有64位,可以同时进行8对字节或4对字或2对双字同时相同操作,还可以进行饱和运算,也就是运算结果有个顶点,
不会溢出,当然也可以进行普通运算.
MM表示64位MMX寄存器.
r32表示32位通用寄存器或esi,edi
m32表示32位内存变量
m64表示64位内存变量
m128表示128位内存变量
imm8表示8位立即数
左操作数为目的操作数,右操作数为源操作数
'|'字符表示每组数据之间的间隔分隔符
movd MM,r32/m32
把 r32/m32 值赋给 MM 的低32位,高32位清零.
movd r32/m32,MM
把 MM 的低32位值赋给 r32/m32.
例:
当MM0 == 1234567887654321 h,eax == 0abc h时,执行movd MM0,eax,则MM0 == 0abc h
当MM0 == 1234567887654321 h,eax == 0abc h时,执行movd eax,MM0,则eax == 87654321 h
movq MM,MM/m64
把源MM/m64的值送入目的MM.
例:
当MM0 == 1234567887654321 h,MM1 == 3141592653 h时,执行movq MM0,MM1,则MM0 == 3141592653 h
movntq m64,MM
m64 <== MM ,MM内容送入m64,不经过cache.
pmovmskb r32,MM
r[0] <== MM[7]
r[1] <== MM[15]
r[2] <== MM[23]
r[3] <== MM[31]
r[4] <== MM[39]
r[5] <== MM[47]
r[6] <== MM[55]
r[7] <== MM[63]
r[31-8] <== 0
paddsb MM,MM/m64
按字节对齐,饱和有符号数(补码)相加(结果= -128~+127,80h~7fh),值送入目的MM.
当结果小于-128时,结果强制转为80h,当结果大于+127时,结果强制转为7fh.
例:
当MM0 == 00 c0 fe 7e 11 h,
MM1 == 12 a6 9c 10 02 h时,执行 paddsb MM0,MM1,
则MM0 == 12 80 9a 7f 13 h
0c0h = -64,0a6h = -90,-64 + (-90) = -154,-154< -128,所以结果为80h
7eh=126,10h=16,126+16=142,142>127,所以结果为7fh
其余的未饱和所以结果正常.
paddsw MM,MM/m64
按字对齐,饱和有符号数(补码)相加(结果= -32768~+32767,8000h~7fffh),值送入目的MM.
运算与paddsb类似,当结果小于-32768时,结果强制转为8000h,当结果大于,+32767时,结果强制转为7fffh.
paddusb MM,MM/m64
按字节对齐,饱和无符号数相加(结果= 0~255,0h~0ffh),值送入目的MM.
当结果大于255时,结果强制转为0ffh.
例:
当MM0 == 23 11 h,MM1 == fc 22 h时,执行paddusb MM0,MM1,则MM0 == ff 33h
23h = 35,0fch = 253,35 + 253 = 288,288> 255,所以结果为0ffh
paddusw MM,MM/m64
按字对齐,饱和无符号数相加(结果= 0~65535,0h~0ffffh),值送入目的MM.
运算与paddusb类似,当结果大于65535时,结果强制转为0ffffh.
psubsb MM,MM/m64
按字节对齐,饱和有符号数(补码)相减(结果= -128~+127,80h~7fh),值送入目的MM.
运算与paddsb类似,当结果小于-128时,结果强制转为80h,当结果大于,+127时,结果强制转为7fh.
psubsw MM,MM/m64
按字对齐,饱和有符号数(补码)相减(结果= -32768~+32767,8000h~7fffh),值送入目的MM.
运算与paddsw类似,当结果小于-32768时,结果强制转为8000h,当结果大于,+32767时,结果强制转为7fffh.
paddb MM,MM/m64
按字节对齐,普通相加,与add指令类似.
例:
当MM0 = 12 34 56 78 ab cd ef feh,
MM1 = 87 69 86 54 3d ea cb 03h,执行paddb MM0,MM1,
则MM0 = 99 9d dc cc e8 b7 ba 01h
paddw MM,MM/m64
按字对齐,普通相加,与add指令类似.
paddd MM,MM/m64
按双字对齐,普通相加.与add指令类似.
paddq MM,MM/m64
按四字对齐,普通相加.
例:
当MM0 == 0fffffffffffffffeh,MM1 == 3h,执行paddq MM0,MM1,则MM0 = 1h
psubb MM,MM/m64
按字节对齐,普通相减,与sub指令类似.
psubw MM,MM/m64
按字对齐,普通相减,与sub指令类似.
psubd MM,MM/m64
按双字对齐,普通相减.与add指令类似.
psubq MM,MM/m64
按四字对齐,普通相减.
例:
当MM0 == 1h,MM1 == 3 h,执行psubq MM0,MM1,则MM0 = 0fffffffffffffffeh
psllw MM,MM/m64 psllw MM,imm8
把目的寄存器按字由源存储器(或imm8 立即数)指定位数逻辑左移,移出的位丢失.
低字移出的位不会移入高字.
例:
当MM0 = 0ffff ffff ffff ffffh,执行psllw MM0,1
则MM0 = 0fffe fffe fffe fffeh
psrlw MM,MM/m64 psrlw MM,imm8
把目的寄存器按字由源存储器(或imm8 立即数)指定位数逻辑右移,移出的位丢失.
高字移出的位不会移入低字.
例:
当MM0 = 0ffff ffff ffff ffffh,执行psrlw MM0,1
则MM0 = 07fff 7fff 7fff 7fffh
pslld MM,MM/m64 pslld MM,MM imm8
把目的寄存器按双字由源存储器(或imm8 立即数)指定位数逻辑左移,移出的位丢失.
低双字移出的位不会移入高双字.
例:
当MM0 = 0ffffffff ffffffffh,执行pslld MM0,1
则MM0 = 0fffffffe fffffffeh
psrld MM,MM/m64 psrld MM,imm8
把目的寄存器按双字由源存储器(或imm8 立即数)指定位数逻辑右移,移出的位丢失.
高双字移出的位不会移入低双字.
例:
当MM0 = 0ffffffff ffffffffh,执行psrld MM0,1
则MM0 = 07fffffff 7fffffffh
pmullw MM,MM/m64
按字对齐,有符号(补码)相乘,取结果低16位,放入目的寄存器的对应字.
例:
当MM0 == 2 acfeh,MM1 == 9 cef3h,执行 pmulhw,则MM0 = 0000 0000 0012 991ah
2 * 9 = 18,18 = 0000 0012h,取低16位 0012 为结果.
0acfeh == -21250,0cef3h == -12557,-21250*-12557 = 266836250 = 0fe7 991a h,取低16位 991a 为结果.
pmulhw MM,MM/m64
按字对齐,有符号(补码)相乘,取结果高16位,放入目的寄存器的对应字.
例:
当MM0 == 2 acfeh,MM1 == 9 cef3h,执行 pmulhw,则MM0 = 0000 0000 0000 0fe7h
2 * 9 = 18,18 = 0000 0012h,取高16位 0000 为结果.
0acfeh == -21250,0cef3h == -12557,-21250*-12557 = 266836250 = 0fe7 991a h,取高16位 0fe7 为结果.
▲注:在MMX指令集中没有除法指令.
﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌
pand MM,MM/m64
64个位'与'操作,结果放入目的寄存器.
pandn MM,MM/m64
目的寄存器按位先取'非',再'与'源寄存器,结果放入目的寄存器.
por MM,MM/m64
64个位'或'操作,结果放入目的寄存器.
pxor MM,MM/m64
64个位'异或'操作,结果放入目的寄存器.
pmaddwd MM,MM/m64
按字对齐有符号(补码)向量点乘.
高32位 | 低32位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器结果: a0*b0+a1*b1 | a2*b2+a3*b3
例:
当MM0 = 0006 8a11 1234 4321h,
MM1 = 0154 c239 ae39 2b35h,当执行pmaddwd MM0,MM1
则MM0 = 1c75a7c1 0583d669h 注意是有符号操作!
pcmpeqb MM,MM/m64
源寄存器与目的寄存器按字节比较,相等就置目的寄存器对应字节为0ffh,否则为00h
例:
当MM0 == 20 11h,MM1 == 21 11h,执行pcmpeqb MM0,MM1,则MM0 = ff ff ff ff ff ff 00 ff h
注:MM0与MM1的高48为0,因为0 == 0,所以置目的寄存器对应字节为0ffh.
pcmpeqw MM,MM/64
源寄存器与目的寄存器按字比较,相等就置目的寄存器对应字为0ffffh,否则为0000h
pcmpeqd MM,MM/m64
源寄存器与目的寄存器按双字比较,相等就置目的寄存器对应双字为0ffffffffh,否则为00000000h
pcmpgtb MM,MM/m64
源寄存器与目的寄存器按字节(有符号补码)比较,
当目的寄存器对应字节大于源寄存器就置目的寄存器对应字节为0ffh,否则为00h
例:
当MM0 == 80 12 11 h,MM1 == 7f 12 10h,执行pcmpgtb MM0,MM1,则MM0 = 00 00 ffh
因为80h = -128,7fh = 127,-128<127,所以结果为00h
pcmpgtw MM,MM/m64
源寄存器与目的寄存器按字(有符号补码)比较,
当目的寄存器对应字大于源寄存器就置目的寄存器对应字为0ffffh,否则为0000h
pcmpgtd MM,MM/m64
源寄存器与目的寄存器按双字(有符号补码)比较,
当目的寄存器对应双字大于源寄存器就置目的寄存器对应双字为0ffffffffh,否则为00000000h
packuswb MM,MM/m64
把目的寄存器按字有符号数压缩为字节无符号数放入目的寄存器低32位
把源寄存器按字有符号数压缩为字节无符号数放入目的寄存器高32位
压缩时负数变为00h,大于255的正数变为0ffh.
高32位 | 低32位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器压缩结果: b0|b1| b2|b3| a0|a1|a2|a3
例:
当MM0 == 7fff 8000 1234 00ae h,MM1 == 00ad 0123 80ff 0100 h,
执行packuswb MM0,MM1,则MM0 = ad ff 00 ff ff 00 ff ae h.
packsswb MM,MM/m64
把目的寄存器按字有符号数压缩为字节有符号数放入目的寄存器低32位
把源寄存器按字有符号数压缩为字节有符号数放入目的寄存器高32位
压缩时小于-128负数变为80h,大于127的正数变为7fh.
高32位 | 低32位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器压缩结果: b0|b1| b2|b3| a0|a1|a2|a3
例:
当MM0 == 0fff ff06 0080 0012 h,MM1 == 0001 8000 ffff 7fff h,
执行packsswb MM0,MM1,则MM0 = 01 80 ff 7f 7f 80 7f 12 h
packssdw MM,MM/m64
把目的寄存器按双字有符号数压缩为单字有符号数放入目的寄存器低32位
把源寄存器按双字有符号数压缩为单字有符号数放入目的寄存器高32位
压缩时小于-32768负数变为8000h,大于32767的正数变为7fffh.
高32位 | 低32位
目的寄存器:a0 | a1
源寄存器: b0 | b1
目的寄存器压缩结果: b0 | b1 | a0 | a1
punpcklbw MM,MM/m64
把目的寄存器与源寄存器的低32位按字节交错排列放入目的寄存器
高32位 | 低32位
目的寄存器: a0|a1|a2|a3|a4|a5|a6|a7
源寄存器: b0|b1|b2|b3|b4|b5|b6|b7
目的寄存器结果:b4|a4|b5|a5|b6|a6|b7|a7
例:
当MM0 == 01 02 03 04 05 06 07 08 h,MM1 == 09 0a 0b 0c 0d 0e 0f 00 h
执行punpcklbw MM0,MM1,则MM0 = 0d 05 0e 06 0f 07 00 08 h
punpcklwd MM,MM/m64
把目的寄存器与源寄存器的低32位按字交错排列放入目的寄存器
高32位 | 低32位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器结果:b2 | a2 | b3 | a3
punpckldq MM,MM/m64
把目的寄存器与源寄存器的低32位按双字交错排列放入目的寄存器
高32位 | 低32位
目的寄存器:a0 | a1
源寄存器: b0 | b1
目的寄存器结果: b1 | a1
punpckhbw MM,MM/m64
把目的寄存器与源寄存器的高32位按字节交错排列放入目的寄存器
高32位 | 低32位
目的寄存器: a0|a1|a2|a3|a4|a5|a6|a7
源寄存器: b0|b1|b2|b3|b4|b5|b6|b7
目的寄存器结果:b0|a0|b1|a1|b2|a2|b3|a3
例:
当MM0 == 01 02 03 04 05 06 07 08 h,MM1 == 09 0a 0b 0c 0d 0e 0f 00 h
执行punpcklbw MM0,MM1,则MM0 = 09 01 0a 02 0b 03 0c 04 h
punpckhwd MM,MM/m64
把目的寄存器与源寄存器的高32位按字交错排列放入目的寄存器
高32位 | 低32位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器结果:b0 | a0 | b1 | a1
punpckhdq MM,MM/m64
把目的寄存器与源寄存器的高32位按双字交错排列放入目的寄存器
高32位 | 低32位
目的寄存器:a0 | a1
源寄存器: b0 | b1
目的寄存器结果: b0 | a0