第41部分-Linux x86 64位汇编MMX使用
使用MMX架构需要一下步骤
- 从整数值创建打包整数值
- 把打包整数值加载到MMX寄存器中
- 对打包整数值执行MMX数学操作。
- 从MMX寄存器获得结果放到内存位置中。
加载和获得打包的整数值,使用movq指令把整数值传送进/出MMX寄存器。
对比打包整数值操作,同时计算多个结果值,单一一组标志不能表示操作的结果。可以从执行数学操作的3种溢出方法中选择: 环绕/带符号饱和/无符号饱和。
带符号和无符号饱和运算方法把溢出情况的结果设置为预先设置的值。
正溢出就设置为最大值,负溢出就设置为最小值,数学角度没有意义。主要是应用于执行图像计算显示图片,正溢出就是最大值为白色,负溢出就是最小值为黑色。
操作的指令有如下:
MMX加法示例
两个long类型整数值存储到单一内存位置,创建打包双字整数值。移动到MMX寄存器,然后通过PADD指令相加,存放到MM0中,最后复制到result内存位置。
.section .data
value1:
.int 10, 20
value2:
.int 30, 40
.section .bss
.lcomm result, 8
.section .text
.globl _start
_start:
nop
movq value1, %mm0
movq value2, %mm1
paddd %mm1, %mm0
movq %mm0, result
movl $60, %eax
movl $0, %ebx
syscall
编译:
as -g -o mmxadd.o mmxadd.s
ld -o mmxadd mmxadd.o
使用gdb调试,在退出前断点进行查看结果。
(gdb) x /2d &value1
0x6000d8: 10 20
(gdb) x /2d &value2
0x6000e0: 30 40
(gdb) x /2x &result
0x6000e8 <result>: 0x00000028 0x0000003c
gdb>info all
…
st0 <invalid float value> (raw 0xffff0000003c00000028)
…
可以在st0寄存器中看到两个结果。MM0就是存在st0中的。
-
- MMX乘法示例
乘法比较困难,因为乘法生产的结果可能会比输入操作数大得多。乘法允许使用两条指令完成乘法操作。
PMULL把每对打包字整数值相乘,结果的低16位存放到目标寄存器。
PMULH把每对打包字整数值相乘,结果的高16位存放到目标寄存器。
带符号的是PMULLW和PMULHW,无符号的是PMULLUW和PMULHUW。
乘法系列中还有一个附加指令是PMADDWD指令。
MMX逻辑和移位
MMX中可用的布尔逻辑指令如下图:
SOURCE可以是MMX寄存器或者64位的内存位置,目标必须是MMX寄存器。
MMX比较
两个值比较指令如下图:
比较结果存放到目标打包整数值中。
-
-
- 示例
-
比较的示例如下,value1和value2被设置为保存4个short类型的整数值。加载到MMX寄存器中,然后使用PCMPEQW指令比较打包整数值的4个字值。结果存放到MM0寄存器,然后传送到result中。
.section .data
value1:
.short 10, 20, -30, 40
value2:
.short 10, 40, -30, 45
.section .bss
.lcomm result, 8
.section .text
.globl _start
_start:
nop
movq value1, %mm0
movq value2, %mm1
pcmpeqw %mm1, %mm0
movq %mm0, result
movl $60, %eax
movl $0, %ebx
syscall
as -g -o mmxcomp.o mmxcomp.s
ld -g -o mmxcomp mmxcomp.o
使用gdb进行调试,开始时如下;
(gdb) x /x &value1
0x6000d8: 0x0014000a
(gdb) x /x &value2
0x6000e0: 0x0028000a
(gdb) x /x &result
0x6000e8 <result>: 0x00000000
执行移动到MM0/MM1后,ST0/ST1的寄存器如下:
st0 <invalid float value> (raw 0xffff0028ffe20014000a)
st1 <invalid float value> (raw 0xffff002dffe20028000a)
执行pcmpeqw后st0寄存器如下:
st0 <invalid float value> (raw 0xffff0000ffff0000ffff)
(gdb) x /8x & result
0x6000e8 <result>: 0x0000ffff 0x0000ffff
我们发现结果如下:
相等的打包整数值,结果相等等于FFFF,不相等的等于0000。