Linux汇编之条件传送

汇编 2015年03月04日 ,

Linux汇编的条件传送指令

MOV指令是可以随意使用且功能强大的指令,它也是在汇编语言中被广泛使用的指令。条件传送(conditinal move)指令是MOV指令发生在特定条件下,条件指令可以避免处理器执行JMP指令,这有利于处理器预取缓存状态,还能在一定程序上提升程序的速度。

在本文枫竹梦将介绍Linux汇编语言(ASM)中如何使用条件传送指令,并演示如何使用它们。

CMOV指令

条件传送指令包含许多指令。其格式如下:

cmovx source, destination

其中x代码一个或者两个字母,表示传送发生的条件。根据EFLAGS寄存器的值进行判断。条件指令使用的特征位如下表:

EFLAGS位 名称 描述
CF 进位(Carry)标志 数学表达式产生了进位或者借位
OF 溢出(Overflow)标志 整数值过大或者过小
PF 奇偶校验(Parity)标志 寄存器包含数学操作造成的错误数据
SF 符号(Sign)标志 指出结果为正还是负
ZF 零(Zero)标志 数据操作的结果为零

条件传送指令成对地分组在一起,两个指令表达相同的含义,但两者具有各自的条件传送指令。条件传送指令分为用于带符号数和无符号数的指令。

无符号数条件传送指令:

指令 描述 EFLAGS状态
CMOVA/CMOVNBE 大于/不小于或者等于 (CF或ZF)=0
CMOVAE/CMOVNB 大于或者等于/不小于 CF=0
CMOVNC 无进位 CF=0
CMOVB/CMOVNAE 小于/不大于或者等于 CF=1
CMOVC 有进位 CF=1
CMOVBE/CMOVNA 小于或者等于/不大于 (CF或ZF)=1
CMOVE/CMOVZ 等于/零 ZF=1
CMOVNE/CMOVNZ 不等于/不为零 ZF=0
CMOVP/CMOVPE 奇偶校验/偶校验 PF=1
CMOVNP/CMOVPO 非奇偶校验/奇校验 PF=0

从表中可以看出,无符号数条件传送指令通过检查进位、零和奇偶标志来确定两个操作数之间的区别。下表是带符号数的条件传送指令。

指令 描述 EFLAGS状态
CMOVGE/CMOVNL 大于或者等于/不小于 (SF异或OF)=0
CMOVL/CMOVNGE 小于/不大于或者等于 (SF异或OF)=1
CMOVLE/CMOVNG 小于或者等于/不大于 ((SF异或OF)或ZF)=1
CMOVO 溢出 OF=1
CMOVNO 未溢出 OF=0
CMOVS 带符号(负) SF=1
CMOVNS 无符号(非负) SF=0

带符号数的条件传送指令通过检查符号位和溢出位进行确定状态。带符号数表无符号数将在以后进行介绍。

条件传送指令一般使用如下方式进行使用:

cmp %ebx, %ecx
cmova %ecx, %ebx

使用CMP指令从第二个操作数减去第一个操作数,并设置EFLAGS寄存器。接着条件传送指令根据EFLAGS标志确定是否进行数据的传送。

使用CMOV指令

使用CMOV的一个小例子如下:

# comv.s - By furzoom @ Mar 4, 2015
.section .data
value:
.int 1, 2, 4, 3
.section .text
.globl _start
_start:
nop
movl value, %ebx
movl $1, %edi
loop:
movl value(, %edi, 4), %eax
cmp %ebx, %eax
cmova %eax, %ebx
inc %edi
cmp $4, %edi
jne loop

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

该程序的功能是查找value数组中最大的值,并将出传送给EBX寄存器。程序中有几处没有接触过的指令,说明如下:

inc %edi

将寄存器EDI的值加1。

jne loop

如果ZF=1则跳转到loop标签,否则顺序执行指令。

使用-gstabs参数汇编该程序,连接后进行调试程序如下:

[mn@furzoom asm]$ as -gstabs -o cmov.o cmov.s
[mn@furzoom asm]$ ld -o cmov cmov.o
[mn@furzoom asm]$ gdb -q cmov
Reading symbols from /home/mn/Desktop/Documents/asm/cmov...done.
(gdb) break *_start+1
Breakpoint 1 at 0x8048075: file cmov.s, line 9.
(gdb) break 19
Breakpoint 2 at 0x8048092: file cmov.s, line 19.
(gdb) run
Starting program: /home/mn/Desktop/Documents/asm/cmov

Breakpoint 1, _start () at cmov.s:9
9         movl value, %ebx
(gdb) cont
Continuing.

Breakpoint 2, loop () at cmov.s:19
19        movl $1, %eax
(gdb) print /d $ebx
$1 = 4
(gdb) 

结果正如期望的那样,最大值4被传送给了EBX寄存器。

其他条件传送指令的使用,与上面的类似,需要根据实际情况进行选取指令。

(完)

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

发表评论

插入图片

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

回到顶部