汇编简单入门教程(十)标志寄存器、串传送指令


 

参考: 《汇编语言》 王爽 第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是从栈中弹出数据,送入标志寄存器中