标志寄存器

标志寄存器

1.0 程序状态字 psw

  • program state word

  • 标志寄存器和其他寄存器不一样,不是用来存放数据

  • 标志寄存器是按位起作用的也就是说它的每一位都有专门的含义,记录特定的信息

  • flag中1,3,5,12,13,14,15在8086CPU中没有使用,不具有任何意义

  • 而2,4,6,7,8,9,10,11位都具有特殊意义

1.1 ZF标志 第6位 零标志位

  • 它记录相关指令执行后 zero

    • 结果为0 ZF = 1
    • 不为0 ZF = 0
  • 例如

  • mov ax, 1
    sub ax, ax
    
    ;指令执行后 结果为零 ZF = 1
    
    mov ax, 2
    sub ax, 1
    
    ;指令执行后 结果不为零 ZF = 0
    ;ZF标记记录相关的计算指令的结果是否为零
    
    • 计算影响标志位的有 add,sub,mul,div,and,or,inc,dec他们都是运算指令

1.2 PF标志 第2位 奇偶标志位

  • 计算结果,所有二进制中1的个数 Parity
    • 为偶数 PF = 1 0000 1111B
    • 为奇数 PF = 0 0000 0111B

1.3 SF标志 第7位 符号标志位

  • 他记录指令执行后 signal
    • 结果为负 SF = 1
    • 结果为正 SF = 0
  • 如何区分正负数 补码

1.4 CF标志 第0位 进制标志位

  • 一般情况下,在进行无符号数运算时,它记录了运算结果的最高位想更高位的进位值,或借位值 carry
  • cpu在运算时,并不会丢弃这个进位值,而是记录在特殊的寄存器的某一位上

1.5 OF标志 第11位 溢出标志位

  • overflow
  • 没有溢出 OF = 0 nv
  • 溢出 OF = 1 ov

1.6 CF和OF的区别

  • CF 是对无符号数的运算才会有意义
  • OF是对有符号的数进行运算才有意义

1.7 adc指令

  • adc 是带位进制的加法指令,也就是加上SF,它利用了CF进制位记录的值
  • 格式: adc 操作对象1 操作对象2
  • 功能:操作对象1=操作对象1+操作对象2+CF
  • 比如:adc ax,bx 实现的功能就是
    • ​ ax = ax + bx + SF
    • adc指令执行后,也可能产生进位值,所以会对CF位进行重新的赋值

1.8 编程题

  • 计算1ef000H 加上 201000H

  • assume cs:code
    	;计算1ef000H 加上 201000H
    code segment
    start: 	mov ax, 001eH			;将第一个数字分开存储在 ax,bx
    		mov bx, 0f000H
    		
    		add bx, 1000H			;用第一个数低位16位加上第二个数的低16位 进位存储在SF中
    		adc ax, 0020H			;这里 ax = ax + 0020H + CF
    									;将结果存储在ax ,bx中
    								;将进位的1 加载高位上  相当于加法的进1  
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    			
    
  • 由于这样的功能,我们可以对任意大的数据进行加法计算

1.9 sbb 指令

  • sbb是带借位的减法指令,他利用了CF位上记录的借位值

  • 格式: sbb操作对象1 操作对象2

  • 功能:操作对象1=操作对象1-操作对象2-CF

  • 比如:sbb ax,bx 实现的功能就是

    • ax = ax - bx - SF
  • 由于这样的功能,我们可以对任意大的数据进行减法法计算

  • 计算003E1000H 减去 00202000H 结果放在ax bx中

  • assume cs:code
    	;计算003E1000H  减去 00202000H 
    code segment
    start: 	mov ax, 003EH		;将第一个数字分开存储在 ax,bx
    		mov bx, 1000H
    		
    		sub bx, 2000H		;用第一个数低位16位减去第二个数的低16位 进位存储在SF中		
    		sbb ax, 0020H		;这里 ax = ax - 0020H - CF	
    							;将结果存储在ax ,bx中
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    
  • sbb和adc是基于同样思想设计的两个指令,思路上相似

2.0 cmp指令

  • cmp 是比较指令,功能相当于减法,只是不保存结果
  • cmp 指令执行后,将对标志寄存器产生影响
  • 其他指令通过识别这些被影响的标志寄存器来得知比较的结果
  • 格式:cmp 操作对象1 - 操作对象2
  • 功能: 不保存计算结果,仅仅根据计算结果,改变标志寄存器的设置
  • 比如 cmp ax, ax
  • 相当于进行 ax- ax的运行 ,结果为0,但是不在ax中保存 仅仅影响标志位
  • 指令执行后
    • ZF = 1 结果是否为0 0=1
    • PF = 1 二进制的1是否为偶数 偶数=1
    • SF = 0 是否为负数 负数=1
    • CF = 0 是否有进制 有 = 1
    • OF = 0 是否有溢出 有 = 1
  • cmp 的设计思想
  • 通过减法运算,改变标志寄存器的值 来记录相关比较的结果

2.1 检测比较结果的条件转移指令

  • 编程题

  • if((ah-bh) == 0){
    	ah = ah + ah
    }else{
    	ah = ah + bh
    }
    //用汇编代码实现
    
  • assume cs:code
    code segment
    start: 	  	mov ah, 1
    			mov bh, 2
    			cmp ah, bh
    			je s
    			add ah, bh
    			jmp short ok
    		s: 	add ah, ah
    		ok: mov ax, 4c00H
    			int 21H
    code ends
    
    end start
    			
    
  • 编程 在一段内存中以字节为单位找出数字为8的个数,将个数存储到ax中

  • assume cs:code,ds:data
    
    data segment
    	db 8,11,22,8,11,22,8,11
    data ends
    
    code segment
    
    start:		mov ax, data				;与数据段挂钩
    			mov ds, ax
    			
    			mov bx, 0					;初始化偏移地址	
    			mov ax, 0					;初始化变量
    			mov cx, 8					;初始化循环次数
    			
    		s:	cmp byte ptr [bx], 8		;进行比较指令 通过je 判断是否为零
    			je ok				
    			jmp short next
    			
    	ok:		inc ax						;为零  ax+1
    	next:	inc bx						;不为零 内存地址+1  比较下一个地址的数据
    			loop s
    			
    			mov ax, 4c00H
    			int 21H
    
    code ends
    
    end start
    

2.2 DF标志和串传送指令

  • DF是第10位,方向标志位 direction
  • 在串指令中,控制每次操作后si,di的增减
  • DF = 0 每次操作si,di 递增
  • DF = 1 每次操作si,di递减
  • 串传送指令 movsb move string byte
  • 功能:以字节为单位的传送
  • 实现:es乘16+di = ds乘16+si
  • 如果DF为0 每次操作si,di 递增
  • 如果DF为1 每次操作si,di 递减
  • 当然也是可以 传送一个字 movsw move string word
  • 8086CPU提供两条指令对DF标志位进行设置
    • cld 指令 将DF标志寄存器为设置为0
    • std 指令 将DF标志寄存器为设置为1

2.3 rep指令 repare

  • 一般和movsw ,movsb配合使用
  • 格式 rep movsb
  • rep 的作用是根据cx的值,重复后面movsb串传送指令

2.4 编程题

  • 将data段中的字符串复制到后面的空间

  • assume cs:code,ds:data
    
    data segment
    	db 'Welcome to masn!'
    	db 16 dup (0)
    data ends
    
    code segment
    
    start:	mov ax, data
    		mov ds, ax			;DS:SI 指向data:0
    		mov es, ax			;ES:DI 指向data:16
    		mov si, 0			
    		mov di, 16
    		
    		mov cx, 16			;rep 循环16次
    		cld					;将DF方向标志寄存器设置为0
    		
    		rep movsb			;进行copy
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    

2.5 pushf 和 popf

  • pushf :将标志寄存器的值压入栈中

  • popf :从栈中弹出数据, 送入标志寄存器

  • assume cs:code
    
    code segment
    
    start:	mov al, 1
    		cmp al, 1
    		
    		pushf			;将标志寄存器的值进行压栈
    		add al, al
    		popf			;弹出标志寄存器
    		
    		mov ax, 4c00H
    		int 21H
    code ends
    
    end start
    
posted @ 2020-12-08 23:03  immortal_mode  阅读(565)  评论(0)    收藏  举报