说明
汇编中的某些指令改变CPU标识位的值,这些命令中,有些指令改变标识位只是其附带效果,比如add指令的和溢出时就会改变CF标识;而另外一些标识,它们的主要作用就是改变标志位,从而控制汇编程序的流程。
以下是几个常用的指令:
CMP
比较。
OF | DF | IF | SF | ZF | AF | PF | CF |
* | * | * | * | * | * |
说明:比较源操作数和目的操作数,“隐含”执行从源操作数中减掉目的操作数的减法操作。这里“隐含”的意思是相应:设置标志位,但不改变操作数!它与SUB的不同在于,CMP不修改目的操作数。
指令格式:
cmp reg, reg
cmp reg, imm
cmp mem, reg
cmp mem, imm
cmp reg, mem
cmp accum, imm
与比较相关的还有几个指令,分别是cmpsb,cmpsw,cmpsd和cmpxchg。
前面三个是同一个类型的,统称为CMPx,它与REP连用,可以用来比较字符串。
CMPx
比较字符串。
OF | DF | IF | SF | ZF | AF | PF | CF |
* | * | * | * | * | * |
说明:比较内存中有DS:(E)SI和ES:(E)DI寻址的字符串。隐含执行源操作数减去目的操作数的减法操作。(E)SI和(E)DI的值依据操作数的大小和方向标志的状态增减。
指令格式:
cmpsb
cmpsw
cmpsd
下面是一个例子:
INCLUDE Irvine32.inc
.data
src DB 12h, 34h, 56h, 78h
dest DB 12h, 34h, 0FFh, 0FFh
.code
main PROC
cld ; 清除方向标识,这样cmpsb操作时,esi和edi会递增
mov ecx, LENGTHOF src ; 用来获取循环次数,这里的ecx的值变成4
mov esi, OFFSET src ; 设置源数据地址
mov edi, OFFSET dest ; 设置目标数据地址
call DumpRegs ; 打印寄存器,与下一次进行比较,比较项主要是edi、esi和ecx
repe cmpsb ; repe表示相等时继续循环
; cmpsb是比较字节
call DumpRegs ; 打印寄存器,
exit
main ENDP
END main
得到的结果如下:
CMPXCHG
比较并交换。
OF | DF | IF | SF | ZF | AF | PF | CF |
* | * | * | * | * | * |
说明:目的操作数和累加器(AL/AX/EAX)比较,如果相等,则源操作数复制到目的操作数,否则目的操作数复制到累加器。
指令格式:
cmpxchg reg, reg
cmpxchg mem, reg
下面是一个例子:
INCLUDE Irvine32.inc
.data
src DB 12h, 34h, 56h, 78h
dest DB 12h, 34h, 0FFh, 0FFh
.code
main PROC
mov esi, OFFSET src ; 设置源数据地址
mov edi, OFFSET dest ; 设置目标数据地址
mov eax, 0FFh ; eax=FFh
cmpxchg [esi], eax ; 因为[esi]的值与eax中的值不相等,所以[esi]的值就复制到了eax中
call DumpRegs ; 打印寄存器,eax的值应该是78563412h
exit
main ENDP
END main
得到的结果如下:
其它的比较测试指令还有如下的:
BT/BTC/BTR/BTS
位测试。
OF | DF | IF | SF | ZF | AF | PF | CF |
? | ? | ? | ? | ? | * |
说明:将指定位n复制到进位标志中,目的操作数包含要操作的位号n。BT将源操作数的位n复制到进位标志中;BTC将源操作数的位n复制到进位标志中并将位n变反;BTR将源操作数的位n复制到进位标志中并将位n清除;BTS将源操作数的位n复制到进位标志中并将位n置1。
指令格式:
BTx r/m16, imm8
BTx r/m16, r16
BTx r/m32, imm8
BTx r/m32, r32
BTx中的x表示C/R/S或者空。注意,这里BTC中的C表示的是取反,而BTR中的R表示的是清除,这个跟一般想象中的C=Clear,R=Reverse不一样。
下面是一个例子:
INCLUDE Irvine32.inc
.data
src DB 12h, 34h, 56h, 78h
dest DB 12h, 34h, 0FFh, 0FFh
.code
main PROC
xor eax,eax ; eax = 0
stc ; cf = 1
call DumpRegs
btc eax, 1 ; 将eax中的bit2取反,所以eax = 0x2, cf = 0
call DumpRegs
exit
main ENDP
END main
得到的结果如下:
TEST
测试。
OF | DF | IF | SF | ZF | AF | PF | CF |
0 | * | * | ? | * | 0 |
说明:在每对操作数的对应数据位之间执行隐含的“与”操作,并设置相应的标志位。它与AND的不同在于,TEST不修改目的操作数。
指令格式:
test reg, reg
test reg, imm
test mem, reg
test mem, imm
test reg, mem
test accum, imm
使用test可以用来判断某个位是否被置位。下面是一个例子:
INCLUDE Irvine32.inc
.code
main PROC
xor eax, eax
or eax, 1 ; eax的bit0被置位
test eax, 1 ; 判断eax的bit0是否被置位
; 从这里可以看到是置位了,所以ZF = 0
call DumpRegs
test eax, 2 ; 判断eax的bit1是否被置位
; 从这里可以看到是置位了,所以ZF = 1
call DumpRegs
exit
main ENDP
END main
得到的结果: