Linux汇编之数据交换

汇编 2015年02月13日 ,

ASM XCHG

交换数据

有时候需要在程序中交换两个元素的位置,使用MOV指令将不得不引进一个临时变量进行两个变量的交换,且需要至少3条指令完成交换。枫竹梦下面介绍Linux中的ASM的数据交换指令。

数据交换指令

数据交换指令集中包含几个指令。每个都有特定的用途,具体如下:

指令 描述
XCHG 在两个寄存器之间或者寄存器和内存位置之间交换值。
BSWAP 反转一个32位的寄存器中的字节顺序。
XADD 交换两个寄存器或者内存位置与寄存器的值并且把总和存储在目标操作数中。
CMPXCHG 把一个值和一个外部值进行比较,并且交换它和另一个值。
CMPXCHG8B 比较两个64位并且交换它们。

XCHG

XCHG(exchange)在两个寄存器之间或者寄存器和内存位置之间交换值。

XCHG operand1, operand2

两个操作数不能同时是内存位置。当一个操作数是内在位置时,处理器的LOCK信号被自动标明,防止在交换过程中任何其他处理器访问该内存位置。可以对8位、16位、32位寄存器使用。 注意:LOCK处理比较耗时。

如下简单的测试代码:

# xchgtest.s - By furzoom @ Feb 13, 2015
.section .text
.globl _start
_start:
nop
movl $1, %eax
movl $2, %ebx
xchg %eax, %ebx

movl $1, %eax
movl $0, %ebx
int $0x80

运行如下:

$ as -gstabs -o xchgtest.o xchgtest.s
$ ld -o xchgtest xchgtest.o
$ gdb -q xchgtest
Reading symbols from /root/Desktop/Documents/asm/xchgtest...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048055: file xchgtest.s, line 6.
(gdb) run
Starting program: /root/Desktop/Documents/asm/xchgtest

Breakpoint 1, _start () at xchgtest.s:6
6         movl $1, %eax
(gdb) step
7         movl $2, %ebx
(gdb) step
8         xchg %eax, %ebx
(gdb) print $eax
$1 = 1
(gdb) print $ebx
$2 = 2
(gdb) step
10        movl $1, %eax
(gdb) print $eax
$3 = 2
(gdb) print $ebx
$4 = 1
(gdb)   

BSWAP

BSWAP(byte swap)反转一个32位的寄存器中的字节顺序。当系统具有不同的字节排列顺序时,它非常有用。对应于大端(big-endian)与小端(little-endian)的字节顺序转换。

BSWAP %eax

如下简单的测试代码:

# swaptest.s - By Furzoom @Feb 13, 2015
.section .text
.globl _start
_start:
nop
movl $0x12345678, %ebx
bswap %ebx
movl $1, %eax
movl $0, %ebx
int $0x80

12345678交换后为78563412

$ as -gstabs -o swaptest.o swaptest.s
$ ld -o swaptest swaptest.o
$ gdb -q swaptest
Reading symbols from /root/Desktop/Documents/asm/swaptest...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048055: file swaptest.s, line 6.
(gdb) r
Starting program: /root/Desktop/Documents/asm/swaptest

Breakpoint 1, _start () at swaptest.s:6
6         movl $0x12345678,  %ebx
(gdb) s
7         bswap %ebx
(gdb) print /x $ebx
$1 = 0x12345678
(gdb) s
8         movl $1, %eax
(gdb) print /x $ebx
$2 = 0x78563412
(gdb) 

XADD

XADD(exchange and add)交换两个寄存器或者内存位置与寄存器的值并且把总和存储在目标操作数中。

XADD source, destination

其中source必须是寄存器,destination可以是寄存器或者内存位置。可以对8位、16位、32位寄存器使用。

使用比较简单,不再给出测试代码。

CMPXCHG

CMPXCHG(compare and exchange)指令比较目标操作数和EAX、AX、AL寄存器的值。如果两个值相等,就把源操作数加载到目标操作数中。如果两个值不相等,就把目标操作数加载到EAX、AX、AL寄存器中。可以对8位、16位、32位寄存器使用。

CMPXCHG source, destination

如下简单测试代码:

# cmpxchgtest.s - By furzoom @Feb 13, 2015
.section .data
data:
.int 10
.section .text
.globl _start
_start:
nop
movl $10, %eax
movl $5, %ebx
cmpxchg %ebx, data

movl $1, %eax
movl $0, %ebx
int $0x80

运行如下:

$ as -gstabs -o cmpxchgtest.o cmpxchgtest.s
$ ld -o cmpxchgtest cmpxchgtest.o
$ gdb -q cmpxchgtest
Reading symbols from /root/Desktop/Documents/asm/cmpxchgtest...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048075: file cmpxchgtest.s, line 9.
(gdb) r
Starting program: /root/Desktop/Documents/asm/cmpxchgtest

Breakpoint 1, _start () at cmpxchgtest.s:9
9         movl $10, %eax
(gdb) step
10        movl $5,  %ebx
(gdb) step
11        cmpxchg %ebx, data
(gdb) x /d &data
0x8049094 <data>:       10
(gdb) step
13        movl $1,  %eax
(gdb) x /d &data
0x8049094 <data>:       5
(gdb) print $ebx
$1 = 5
(gdb) print $eax
$2 = 10
(gdb)       

CMPXCHG8B

CMPXCHG8B(compare and exchange 8 bytes)指令与CMPXCHG类似,区别再于它处理8个字节。

CMPXCHG8B destination

destination操作数引用一个内存位置,并与EDX和EAX组成的值进行对比,EDX为高位寄存器,EAX为低位寄存器,本文记为EDX:EAX。如果EDX:EAX与destination匹配,就将ECX:EBX组成的值加载到destination中;如果不相等,将destination中的值加载到EDX:EAX中。

如下简单测试代码:

# cmpxchg8btest.s - By furzoom @ Feb 13, 2015
.section .data
data:
.byte 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
.section .text
.globl _start
_start:
nop
movl $0x44332211, %eax
movl $0x88776655, %edx
movl $0x11111111, %ebx
movl $0x22222222, %ecx
cmpxchg8b data

movl $1, %eax
movl $0, %ebx
int $0x80

运行如下:

$ as -gstabs -o cmpxchg8btest.o cmpxchg8btest.s
$ ld -o cmpxchg8btest cmpxchg8btest.o
$ gdb -q cmpxchg8btest
Reading symbols from /root/Desktop/Documents/asm/cmpxchg8btest...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048075: file cmpxchg8btest.s, line 9.
(gdb) run
Starting program: /root/Desktop/Documents/asm/cmpxchg8btest

Breakpoint 1, _start () at cmpxchg8btest.s:9
9         movl $0x44332211, %eax
(gdb) step
10        movl $0x88776655, %edx
(gdb) step
11        movl $0x11111111, %ebx
(gdb) step
12        movl $0x22222222, %ecx
(gdb) step
13        cmpxchg8b data
(gdb) step
15        movl $1, %eax
(gdb) x /8xb &data
0x804909c <data>:       0x11    0x11    0x11    0x11    0x22    0x22    0x22   0x22
(gdb)

注意:内存数据与寄存器内数据的顺序。

应用

数据交换指令最大的应用就是在排序时进行数据的交换。

如无特别说明,本站文章皆为原创,若要转载,务必请注明以下原文信息:
日志标题:《Linux汇编之数据交换》
日志链接:http://furzoom.com/linux-asm-data-exchange-instruction/
博客名称:枫竹梦

发表评论

插入图片

NOTICE1:请申请gravatar头像,没有头像的评论可能不会被回复!

回到顶部