MMX指令有8个64位寄存器(MM0~MM7),不过可惜都是借的FPU的, FPU原来有8个80位寄存器(st(0)~st(7)),现在用在了MMX上,所以用之后要加上一条EMMS指令,用以复位.
MMX寄存器有64位,可以同时进行8对字节或4对字或2对双字同时相同操作,还可以进行饱和运算,不会溢出,当然也可以进行普通运算.
特别要注意的一点是:在x86上,一个字,WORD的长度是16位,而在ARM上,一个WORD的长度是32位。
描述约定:
MM表示64位MMX寄存器.
r32表示32位通用寄存器或esi,edi
m32表示32位内存变量
m64表示64位内存变量
m128表示128位内存变量
imm8表示8位立即数
左操作数为目的操作数,右操作数为源操作数
1. 数据搬移指令
movd MM,r32/m32
把 r32/m32 值赋给 MM 的低32位,高32位清零.
movd r32/m32,MM
把 MM 的低32位值赋给 r32/m32.
例:
当 MM0 == 0x12345678 87654321,eax == 0x0abc 时, 执行movd MM0,eax, 则 MM0 == 0x 0abc
当 MM0 == 0x12345678 87654321,eax == 0x0abc 时, 执行movd eax,MM0, 则 eax == 0x 87654321
movq MM,MM/m64
把源MM/m64的值送入目的MM.
例:
当 MM == 0x1234567887654321, MM1 == 0x3141592653时,执行movq MM0,MM1,则MM0 == 0x3141592653
2. 饱和算数加减运算指令
paddsb MM,MM/m64
按字节对齐,饱和8位有符号数相加
当结果小于-128时,结果强制转为80h,当结果大于+127时,结果强制转为7fh.
例:
当 MM0 == 0x 00 c0 fe 7e 11,
MM1 == 0x 12 a6 9c 10 02, 执行 paddsb MM0,MM1,
则 MM0 == 0x 12 80 9a 7f 13
paddsw MM,MM/m64
按字对齐,饱和16位有符号数相加
结果强制到 -32768,+32767之间
paddusb MM,MM/m64
按字节对齐,饱和无符号数相加(结果= 0~255,0h~0ffh),值送入目的MM.
当结果大于255时,结果强制转为0ffh,结果小于0时强制为0
paddusw MM,MM/m64
按字对齐,饱和无符号数相加(结果= 0~65535,0h~0ffffh),值送入目的MM.
运算与paddusb类似,当结果大于65535时,结果强制转为0ffffh.
注:减法指令与上述类似,总结为下表:
PADDS[B,W] | 饱和有符号数加[byte, word] |
PADDUS[B,W] | 饱和无符号数加[byte, word] |
PSUBS[B,W] | 饱和有符号数减[byte, word] |
PSUBUS[B,W] | 饱和无符号数减[byte, word] |
3. 普通算数加减运算指令
paddb MM,MM/m64
按字节对齐,普通相加,与add指令类似.
例:
当MM0 = 12 34 56 78 ab cd ef fe,
MM1 = 87 69 86 54 3d ea cb 03,执行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
小结:
1. 饱和算数加减运算的指令中有S标记
2. 饱和运算只有8位和16位两种,分为无符号和有符号。