一、状态寄存器
首先看看:状态寄存器(即标志寄存器)
psw(program status word)程序状态字(即标志)寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,
如下所示:
条件码:
①of(overflow flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配。
②sf(sign flag)符号标志,结果为负时置1,否则置0。
③zf(zero flag)零标志,运算结果为0时置1,否则置0。
④cf(carry flag)进位标志,进位时置1,否则置0.注意:carry标志中存放计算后最右的位。
⑤af(auxiliary carry flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。
有进位时1,否则置0。
⑥pf(parity flag)奇偶标志.结果操作数中1的个数为偶数时置1,否则置0。
控制标志位:
⑦df(direction flag)方向标志,在串处理指令中控制信息的方向。
⑧if(interrupt flag)中断标志。
⑨tf(trap flag)陷井标志。
test和cmp指令运行后都会设置标志位,为举例方便说一下jnz和jz
测试条件
jz zf=1
jnz zf=0
即jz=jump if zero (结果为0则设置zf零标志为1,跳转)
jnz=jump if not zero
二、test指令和cmp指令
好,接着来看test和cmp
1、test指令
test属于逻辑运算指令
功能:执行bit与bit之间的逻辑运算
测试(两操作数作与运算,仅修改标志位,不回送结果)。
test对两个参数(目标,源)执行and逻辑操作,并根据结果设置标志寄存器,结果本身不会保存。est ax, bx 与 and ax, bx 命令有相同效果
语法:test r/m,r/m/data
影响标志:c,o,p,z,s(其中c与o两个标志会被设为0)
运用举例:
1.test用来测试一个位,例如寄存器:
test eax, 100b; b后缀意为二进制
jnz ******; 如果eax右数第三个位为1,jnz将会跳转
jnz跳转的条件非0,即zf=0,zf=0意味着零标志没被置位,即逻辑与结果为1。
2.test的一个非常普遍的用法是用来测试一方寄存器是否为空:
test ecx, ecx
jz somewhere
如果ecx为零,设置zf零标志为1,jz跳转
2、cmp指令
cmp属于算术运算指令
功能: 比较两个值(寄存器,内存,直接数值)
语法: cmp r/m,r/m/data
标志位: c,p,a,z,o
cmp比较.(两操作数作减法,仅修改标志位,不回送结果)。
cmp实际上是只设置标志不保存结构的减法,并设置z-flag(零标志)。
零标志很像carry,也是内部标志寄存器的一位。
例如:
cmp eax, 2; 如果eax-2=0即eax=2就设置零标志为1
jz ****; 如果设置了零标志就跳转
得出的结论
test逻辑与运算结果为零,就把zf(零标志)置1;
cmp 算术减法运算结果为零,就把zf(零标志)置1。
对于jz和jnz,查看代码和理解汇编代码时,直接判断test和cmp的运算结果决定是否跳转,至于zf标记位是系统得知运算结果的标记位。
三、 直接标志转移
指令格式 机器码 测试条件 如...则转移
jc 72 c=1 有进位
jnc 73 c=0 无进位
jz/je 74 z=1 零/
jnz/jne 75 z=0 不为零/
js 78 s=1 负号
jns 79 s=0 正号
jo 70 o=1 有溢出
jno 71 o=0 无溢出
jp/jpe 7a p=1 奇偶位为偶
jnp/ipo 7b p=0 奇偶位为奇
四、间接标志转移
先用cmp指令比较再用下面的判断(少了一个 je 为等于):
指令格式 机器码 测试格式 如...则转移
ja/jnbe() 77 cz=0 >/
jae/jnb() 73 c=0 >=/
jb/jnae() 72 c=1
jbe/jna() 76 cz=1 <=/
jg/jnle() 7f (so)z=0 >/
jge/jnl() 7d so=0 >=/
jl/jnge() 7c so=1
jle/jng() 7e (so)z=1 <=/
小结
test指令
将两个操作数进行逻辑与运算,并根据运算结果设置相关的标志位。test命令的两个操作数不会被改变。运算结果在设置过相关标记位后会被丢弃。
影响的标志位cf,zf,of,sf,pf
cmp指令
比较指令。cmp的功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
影响的标志位cf,zf,of,af,pf