疯狂的暑假学习之 汇编入门学习笔记 (十)—— 标志寄存器
参考: 《汇编语言》 王爽 第11章
CPU内部有一种特殊的寄存器叫标志寄存器(flag),它与ax,bx,cx等其他寄存器不同,它不是用来存放数据的,而是用来存放状态的。flag寄存器是按位器作用的,即只有0和1。
flag寄存器的结构:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OF DF IF SF ZF AF PF CF
在debug中标志位的表示:
标志 1 0
of OV NV
sf NG PL
zf ZR NZ
pf PE PO
cf CY NC
df DN UP
1. ZF标志
零标志位。如果上条相关指令结果为0,那门ZF=1,不为0那门ZF=0
例子:
mov ax,1 sub ax,1
mov ax,1 and ax,0
执行后zf为1
add,sub,mul,div,inc,or,and等这些运算指令会影响标志寄存器
mov,push,pop等转移指令对标志寄存器没有影响
2. PF 标志
奇偶标志位。是0是1的规则 ,类似于奇校验。
如果上条相关指令结果二进制中1的个数为偶数,则PF=1,为奇数则PF=0 。
例子:
mov al,1 add al,10
al = 00001011b
pf = 0
mov al,1 or al,2
al = 00000011b
pf = 1
3. SF标志
符号标志位。
如果上条相关指令结果为负数,则SF=1,正数则SF=0
本质就是看第一位是否为1
mov al,10000001b add al,1
SF = 1
4. CF标志
表示无符号计算中的进位(注意:inc和dec指令是不影响CF的,但会影响ZF与OF)
例子:
mov al,98H add al,al
CF = 1
相减为负数,也会使得CF = 1
mov ax,1 sub ax,2
5. OF标志
表示有符号计算的溢出(注意:inc和dec指令是会影响OF的)
例如8位补码 表示的数的范围 -128~127
例子:
mov al,0F0H add al,88H
-16+(-120) = -136
超过了范围,所以OF = 1
6. abc 指令
带进位的加法指令
abc ax,bx
相当于(ax)=(ax)+(bx)+CF
例子:实现两个128位数据相加
assume cs:code,ds:data data segment db 88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h,88h db 11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h,11h data ends code segment start: mov ax,data mov ds,ax mov si,0 mov di,16 mov cx,8 call add128 add128: push ax push cx push si push di sub ax,ax ;将CF设置为0 s: mov ax,[si] adc ax,[di] mov [si],ax inc si ;不用add是因为add会改变CF的值 inc si inc di inc di loop s pop di pop si pop cx pop ax code ends end start
7. sbb指令
sbb是带借位的减法指令
sbb ax,bx 相当于(ax)=(ax)-(bx)-CF
8. cmp指令
cmp是比较指令,相当于减法,但不保存结果只改变flag
cmp ax,bx
对于无符号数来说
如果(ax)=(bx) 则(ax)-(bx)=0, 所以:zf = 1;
如果(ax)!=(bx) 则(ax)-(bx)!=0,所以:zf = 0;
如果(ax)< (bx) 则(ax)-(bx)会产生错位,所以:cf = 1;
如果(ax)>(bx) 则(ax)-(bx)不会产生错位,结果也不可能为0, 所以:cf = 0 并且zf = 0;
可以这么说:
zf = 1 说明 (ax)=(bx)
zf
= 0 说明 (ax)!=(bx)cf
= 1 说明(ax)< (bx)cf
= 0 说明 (ax)>= (bx)cf
= 0 并且zf = 0 , 说明(ax)>(bx)cf = 1 或者zf=1, 说明 (ax)<=(bx)
对于有符号数来说
zf = 1 说明 (ax)=(bx)
zf = 0 说明 (ax)!=(bx)
sf=1 并且 of=0,说明(ax)<(bx)
sf=0 并且 of=1,说明(ax)<(bx)
sf=1 并且 of=1,说明(ax)>(bx)
sf=0 并且 of=0,说明(ax)>=(bx)
9. 检测比较结果的条件转移指令
对于无符号数:
je 等于则转移 zf=1
jne 不等于则转移 zf=0
jb 低于则转移 cf=1
jnb 不低于则转移 cf=0
ja 高于则转移 cf=0且cf = 0
jna 不高于则转移 cf=1或zf=1
各个字母的意思:
j:jmp
e:equal
ne:not equal
b:below
nb:not below
a:above
na:not above
例如实现:如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)
cmp ah,bh je s add ah,bh s: add ah,ah
例子:计算data段中为8的数的个数,记录在ax中
assume cs:code,ds:data data segment db 8,11,23,8,2,3,8,8 data ends code segment start: mov ax,data mov ds,ax mov si,0 mov ax,0 mov cx,8 s: cmp byte ptr ds:[si],8 jne next inc ax next: inc si loop s mov ax,4c00H int 21H code ends end start
10. DF 标志位和串传送指令
df=0 每次操作后si、di递增;
df=1 每次操作后si、di递减;
movsb
功能:将ds:si 指向的内存单元中的字节送入es:di中,然后根据标志寄存器df位的值,将si和di递增或递减1
相当于:
(1)((es)*16+(di))=((ds)*16+(si))
(2)df=0则:(si)=(si)+1
(di)=(di)+1
df=1则:(si)=(si)-1
(di)=(di)-1
movsw
功能:于movsb相同,只是是传送一个字,然后就是si和di是递增或递减2
指令cld,std
cld:将df设置为0
std:将df设置为1
rep指令
功能:根据cx的值重复执行,后面的串指令。
格式:rep movsb
例子:复制data中的‘Welcome to masm!‘
assume cs:code,ds:data data segment db 'Welcome to masm!' db 16 dup(0) data ends code segment start: mov ax,data mov ds,ax mov es,ax mov di,16 mov si,0 mov cx,16 cld rep movsb mov ax,4c00h int 21h code ends end start
11. pushf和popf
pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据,送入标志寄存器中