汇编语言 第十一章-标志寄存器

flag

前言

8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW)。

我们己经使用过8086CPU的ax、bx、cx、dx、si、di、bp、sp、ip、cs、ss、ds、es等13个寄存器了。

本章中的标志寄存器(以下简称为flag)是我们要学习的最后一个寄存器。

flag 和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。

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

8086CPU的flag寄存器的结构:

flag的1、3、5、12、13、14、15位在8086CPU中没有使用,不具有任何含义。而0、2、4、6、7、8、9、10、11位都具有特殊的含义。

ZF标志-Zero Flag

flag的第6位是ZF,零标志位。    

它记录相关指令执行后, 结果为0 ,ZF = 1 结果不为0,ZF = 0

例如:      

mov ax,1      sub ax,1      

指令执行后,结果为0,则ZF = 1。           

mov ax,2          sub ax,1      

指令执行后,结果为1,则ZF = 0。

对于ZF的值,我们可以这样来看,ZF标记相关指令的计算结果是否为0,如果为0,则在ZF要记录下“是0”这样的肯定信息。而对    “是0”  给予的肯定或者否定的判断,用0和1表示。0代表否定,1代表肯定

指令: mov ax,1        and ax,0    执行后,结果为0,则ZF=1,表示“结果是0”。    

指令: mov ax,1        or ax,0       执行后,结果不为0,则ZF=0,表示“结果非0”。

注意:    在8086CPU的指令集中,有的指令的执行是影响标志寄存器的,比如:add、sub、mul、div、inc、or、and等,它们大都是运算指令(进行逻辑或算术运算);    

有的指令的执行对标志寄存器没有影响,比如:mov、push、pop等,它们大都是传送指令。

我们在使用一条指令的时候,要注意这条指令的全部功能,其中包括,执行结果对标记寄存器的哪些标志位造成影响。

PF标志-Parity Flag

flag的第2位是PF,奇偶标志位。    

它记录指令执行后,结果的所有二进制位中1的个数: 为偶数,PF = 1; 为奇数,PF = 0。

示例

指令:mov al,1        add al,10    执行后,结果为00001011B,其中有3(奇数)个1,则PF=0;

指令:mov al,1        or al,10    执行后,结果为00000011B,其中有2(偶数)个1,则PF=1;

SF标志-Sign Flag

flag的第7位是SF,符号标志位。    

它记录指令执行后, 结果为负,SF = 1; 结果为正,SF = 0

我们需要先来认识一下有符号数与补码:

我们知道计算机中通常用补码来表示有符号数据。

计算机中的一个数据可以看作是有符号数,也可以看成是无符号数。

比如: 00000001B ,可以看作为无符号数 1 ,或有符号数+1;

10000001B ,可以看作为无符号数129,也可以看作有符号数-127。

示例       mov al,10000001B       add al,1       结果: (al)=10000010B

我们可以将add指令进行的运算当作无符号数的运算,那么add指令相当于计算129+1,结果为130(10000010B);

也可以将add指令进行的运算当作有符号数的运算,那么add指令相当于计算-127+1,结果为-126(10000010B)。

不管我们如何看待,CPU 在执行add等指令的时候,就已经包含了两种含义,也将得到用同一种信息来记录的两种结果。 关键在于我们的程序需要哪一种结果。

SF 标志,就是CPU对有符号数运算结果的一种记录 ,它记录数据的正负。    

在我们将数据当作有符号数来运算的时候,可以通过它来得知结果的正负。

如果我们将数据当作无符号数来运算,SF的值则没有意义,虽然相关的指令影响了它的值

CF标志-Carry Flag

flag的第0位是CF,进位标志位。

一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值或从更高位的借位值

对于位数为N的无符号数来说,其对应的二进制信息的最高位,即第N-1位的最高有效位,而假想存在的第N位,就是相对于最高有效位的更高位。

我们知道,当两个数据相加的时候,有可能产生从最高有效位向更高位的进位。

比如,两个8 位数据:98H+98H,将产生进位。  1001 1000B  +  1001 1000B.最高位的1+1进到第九位,由于这个进位值在8位数中无法保存,我们在前面的课程中,类似的进位就只是简单地说这个进位值丢失了。

其实CPU在运算的时候,并不丢弃这个进位值,而是记录在一个特殊的寄存器的某一位上。 8086CPU 就用flag的CF位来记录这个进位值。

在Debug中,我们可以看到类似下面的信息:

(星星指的是每一个cpu的值都不一样,占位用)

比如,下面的指令:    

mov al,98H    

add al,al  ;

执行后: (al)=30H,CF=1,                    ;

CF记录了最高有效位向更高位的进位值

实战:

另外一种情况,而当两个数据做减法的时候,有可能向更高位借位。

比如,两个 8 位数据:97H-98H,将产生借位,借位后,相当于计算197H-98H。    

而flag的CF位也可以用来记录这个借位值。

比如,两个 8 位数据:97H-98H,将产生借位,借位后,相当于计算197H-98H。    

而flag的CF位也可以用来记录这个借位值。

实战:

OF标志-Overflow Flag

我们先来谈谈溢出的问题。    

在进行有符号数运算的时候,如结果超过了机器所能表示的范围称为溢出。

那么,什么是机器所能表示的范围呢?

比如:add al,3 ,那么对于 8 位的有符号数据,机器所能表示的范围就是-128~127。

如果运算结果超出了机器所能表达的范围,将产生溢出。

注意,这里所讲的溢出,只是对有符号数运算而言

(就像进位只是相对于无符号数而言!) 下面我们看这个溢出的例子。

我们可以看到,在七位,有两个1相加。如果是看成有符号,那么第八位就是用来表示符号的,如果第七位相加进位到第八位,那么这就叫溢出

assume cs:code

code segment

start: 	mov al, 01100010b
		add al, 01100011b
		
		mov ax, 4c00h
		int 21h
code ends

end start

记住,一定要注意CF和OF的区别:    

CF是对无符号数运算有意义的标志位;    

而OF是对有符号数运算有意义的标志位。

对于无符号数运算,CPU用CF位来记录是否产生了进位;

对于有符号数运算,CPU 用 OF 位来记录是否产生了溢出, 当然,还要用SF位来记录结果的符号。!!!

对于有无符号,计算机是分不清楚状况的,因此他必须两种都记载着,要怎么用,看的是你当他是什么!

例如:mov al, 98d    (0110 0010B)         

add  al, 99d (0110 0011B) 

对于无符号数运算,98+99没有进位,CF=0;

对于有符号数运算,98+99发生溢出,OF=1。

adc指令

介绍

adc是带进位加法指令 ,它利用了CF位上记录的进位值。

格式:  adc 操作对象1,操作对象2

功能:    操作对象1=操作对象1+操作对象2+CF

比如:adc ax,bx 实现的功能是:    (ax)=(ax)+(bx)+CF

adc指令示例(一)

mov ax,2

mov bx,1

sub bx,ax

adc ax,1   

执行后,(ax)=4。   adc执行时,相当于计算: (ax)+1+CF=2+1+1=4。

adc指令示例(二)

mov ax,1

add ax,ax

adc ax,3   执行后,(ax)=5。  

adc执行时,相当于计算: (ax)+3+CF=2+3+0=5。

在执行 adc 指令的时候加上的 CF 的值的含义,由 adc指令前面的指令决定的,也就是说,关键在于所加上的CF值是被什么指令设置的。

显然,如果CF 的值是被sub指令设置的,那么它的含义就是借位值;如果是被add指令设置的,那么它的含义就是进位值。

实操讲解

思考:    inc和loop指令不影响CF位,

编程计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。      

mov ax,001EH      

mov bx,0F000H      

add  bx,1000H      

adc  ax,0020H

adc 指令执行后,也可能产生进位值,所以也会对CF位进行设置。

由于有这样的功能,我们就可以对任意大的数据进行加法运算

例如,编程计算 1E F000 1000H+20 1000 1EF0H,

结果放在 ax(高16位),bx(次高16位),cx(低16位)中。

程序可以如此实现:      

我们将第一个数的低位,中位,高位分别放在ax,bx,cx中,然后用第二个数的低位,中位,高位分别与ax,bx,cx相加,就得到结果了

mov ax,001EH      

mov bx,0F000H      

mov cx,1000H      

add cx,1EF0H      

adc bx,1000H      

adc ax,0020H

下面我们,编写一个子程序,对两个128位数据进行相加。 名称:add128 功能:两个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

        mov ax,4c00h
	int 21h

;编写一个子程序,对两个128位数据进行相加。

;名称:add128
;功能:两个128位数据进行相加
;参数:
;   ds:si指向存储第一个数的内存空间,因数据为128位,所以需要8个字单元,由低地址单元到高地址单元依次存
;   放128位数据由低到高的各个字。运算结果存储在第一个数的存储空间中。 

;   ds:di指向存储第二个数的内存空间
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
        inc si
        inc di
        inc di
        loop s

        pop di
        pop si
        pop cx
        pop ax
        ret       
        
code ends

上面的程序中,能不能将4个inc指令,用:          

add si,2          add si,2    取代?

答案是不能的。因为add会影响CF、

cmp指令

介绍

cmp 是比较指令,功能相当于减法指令,只是不保存结果

cmp 指令执行后,将对标志寄存器产生影响。

其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

格式:

cmp 操作对象1,操作对象2

功能:计算操作对象1–操作对象2

但并不保存结果,仅仅根据计算结果对标志寄存器进行设置

比如:

cmp ax,ax

做(ax)–(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关各位。

指令执行后:       ZF=1,       PF=1,       SF=0,       CF=0,       OF=0。

下面的指令:      

mov ax,8        

mov bx,3        

cmp ax,bx

执行后: (ax) = 8         ZF=0,         PF=1,         SF=0,         CF=0,         OF=0。

使用

无符号运算

其实,我们通过cmp 指令执行后,相关标志位的值就可以看出比较的结果。

例如:cmp ax,bx

现在我们可以看出比较指令的设计思路

即:通过做减法运算,影响标志寄存器,标志寄存器的相关位记录了比较的结果。

反过来看上面的例子 cmp ax,ax

同 add、sub 指令一样,CPU 在执行cmp指令的时候,也包含两种含义:

进行无符号数运算和进行有符号数运算

所以利用cmp指令可以对无符号数进行比较,也可以对有符号数进行比较。

有符号运算

下面我们再来看一下如果用cmp来进行有符号数比较时,我们要注意哪些标志位!

我们以cmp ah,bh为例进行说明:    

如果(ah)=(bh) 则(ah)-(bh)=0,所以:ZF=1;    

如果(ah)≠(bh) 则(ah)-(bh) ≠0,所以:ZF=0;    

所以,我们根据cmp指令执行后ZF的值,就可以知道两个数据是否相等。 这个和无符号运算是一样的

我们继续看,如果(ah)<(bh)则可能发生什么情况呢?

对于有符号数运算,在 (ah)<(bh) 情况下,(ah)-(bh)显然可能引起SF=1,即结果为负。

比如:

(ah) = 1,(bh) = 2: 则(ah)-(bh)=1111B  ->  0FFH,0FFH 为 -1 的补码,因为结果为负,所以SF=1。

(ah) = -2 ,  (bh) = -1  则(ah)-(bh)=(-2)-(-1)=0FFH,因为结果为负,所以SF=1。

通过上面的例子,我们是不是可以得到这样的结论: cmp 操作对象1,操作对象2 指令执行后,SF=1,就说明操作对象1<操作对象2?    

当然不是。 我们再看下面这个例子。

(ah)=22H,(bh)=0A0H: 则(ah)-(bh)=34-(-96)=130=82H,82H是   -126的补码,所以SF=1。

这里虽然SF=1,但是并不能说明(ah)<(bh),因为显然34>-96。

两个有符号数A 和B 相减,得到的是负数,那么可以肯定A<B,这个思路没有错误

关键在于我们根据什么来断定得到的是一个负数。 CPU将 cmp 指令得到的结果记录在flag的相关标志位中。

如果没有溢出发生的话,那么,实际结果的正负和逻辑上真正结果的正负就一致了。

所以,我们应该在考察SF(得知实际结果的正负)的同时考察OF(得知有没有溢出)

就可以得知逻辑上真正结果的正负,同时就可以知道比较的结果。

下面,我们以cmp ah,bh为例,总结一下C PU执行cmp指令后,SF和OF的值是如何来说明比较的结果的。

(1)如果SF=1,而OF=0 OF=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负;

因SF=1,实际结果为负,所以逻辑上真正的结果为负,所以(ah)<(bh)。

(2)如果SF=1,而OF=1 OF=1 ,说明有溢出,逻辑上真正结果的正负≠实际结果的正负; 简单分析一下,就可以看出,如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。这样,SF=1,OF = 1 ,说明了(ah)>(bh)。

(3)如果SF=0,而OF=1 OF=1 ,说明有溢出,逻辑上真正结果的正负≠实际结果的正负; 简单分析一下,就可以看出,如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负。这样,SF=0,OF = 1 ,说明了(ah)<(bh)。

(4)如果SF=0,而OF=0 OF=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负; 因SF=0,实际结果非负,所以逻辑上真正的结果必然非负。所以(ah)≥(bh)。

小总结

规律总结

情况SFOF实际结果逻辑结果比较关系
110负数负数(ah) < (bh)
200非负数非负数(ah) ≥ (bh)
311负数正数(ah) > (bh)
401非负数负数(ah) < (bh)

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

下面的内容中我们将学习一些根据cmp指令的比较结果(即,cmp指令执行后,相关标志位的值)进行工作的指令。

它们检测的是哪些标志位呢? 就是被cmp指令影响的那些,表示比较结果的标志位。

这些条件转移指令通常都和cmp相配合使用,就好像 call 和 ret 指令通常相配合使用一样。

因为 cmp 指令可以同时进行两种比较,无符号数比较和有符号数比较,所以根据 cmp 指令的比较结果进行转移的指令也分为两种,

即:

根据无符号数的比较结果进行转移的条件转移指令,它们检测ZF、CF的值;

和根据有符号数的比较结果进行转移的条件转移指令,它们检测 SF、OF和 ZF的值。 

这些指令比较常用,它们都很好记忆,它们的第一个字母都是j,表示jump;后面的:  

e:表示equal;

ne:表示not equal;  

b:表示below;

nb:表示not below;  

a:表示above;

na:表示not above。

DF标志和串传送指令

介绍

flag的第10位是DF,方向标志位。

在串处理指令中,控制每次操作后si,di的增减。

DF = 0:每次操作后si,di递增;

DF = 1:每次操作后si,di递减。

movsb movsw rep

格式1: movsb          

功能:(以字节为单位传送)

(1)   ((es)×16 + (di)) = ((ds) ×16 + (si))

(2)   如果DF = 0则: (si) = (si) + 1      (di) = (di) + 1        

        如果DF = 1则: (si) = (si) - 1      (di) = (di) - 1

movsb 的功能是将 ds:si 指向的内存单元中的字节送入 es:di中,然后根据标志寄存器DF位的值,将 si和di递增或递减。

当然,也可以传送一个字: movsw

格式2:movsw

功能:(以字为单位传送)    

将 ds:si指向的内存字单元中word送入es:di中,然后根据标志寄存器DF位的值,将si和di递增2或递减2。

movsb和movsw进行的是串传送操作中的一个步骤。

一般来说,movsb 和 movsw 都和rep配合使用,

格式如下:

rep movsb

rep的作用是根据cx的值,重复执行后面的串传送指令。

由于每执行一次movsb指令si和di都会递增或递减指向后一个单元或前个单元,则rep movsb就可以循环实现(cx)个字符的传送。

cld std

由于flag的DF位决定着串传送指令执行后,si和di改变的方向,所以CPU应该提供相应的指令来对DF位进行设置,从而使程序员能够决定传送的方向。

8086CPU提供下而两条指令对DF位进行设置:

cld指令:将标志寄存器的DF位置0  ---  clear df

std指令:将标志寄存器的DF位置1  --- set df

案例分析

我们来看两个程序  

编程1:     用串传送指令,将data段中的第一个字符串复制到它后面的空间中。    

 data segment
    db ‘Welcome to masm!’
    db  16 dup (0)
   data ends

我们分析一下,使用串传送指令进行数据的传送,需要给它提供一些必要的信息,它们是:

① 传送的原始位置:ds:si;  

② 传送的目的位置:es:di;    

③ 传送的长度:cx;    

④ 传送的方向:DF。

实战

assume cs:code

data segment
    db 'Welcome to masm!'
    db 16 dup (0)
data ends

code segment
start:	mov ax,data
		mov ds,ax
		mov si,0       	  ;ds:si指向data:0
		mov es,ax
		mov di,16     	  ;es:di指向data:16
		mov cx,16  	 	  ;(cx)=16,rep循环16次
		
		cld               ;设置DF=0,正向传送
		rep movsb
		
		mov ax, 4c00h
		int 21h
code ends

end start

编程2:     用串传送指令,将F000H段中的最后16个字符复制到data段中。       

data segment
      db 16 dup (0)
   data ends

我们还是先来看一下应该为串传送指令提供什么样的信息: 要传送的字符串位于F000H段的最后16个单元中,那么它的最后一个字符的位置:F000:FFFF,是显而易见的。 我们可以将ds:si指向 F000H段的最后一个单元,将es:di指向data段中的最后一个单元,然后逆向(即从高地址向低地址)传送16个字节即可。

实战

assume cs:code

data segment
    db 16 dup (0)
data ends

code segment
start:	mov ax,0f000h
		mov ds,ax
		mov si,0ffffh 		;ds:si指向f000:ffff
		mov ax,data
		mov es,ax
		mov di,15     		;es:di指向data:15
		mov cx,16   		;(cx)=16,rep循环16次
		
		std               	;设置DF=1,逆向传送
		rep movsb
		
		mov ax, 4c00h
		int 21h
code ends

end start

pushf 和 popf

pushf :将标志寄存器的值压栈; popf :从栈中弹出数据,送入标志寄存器中。

pushf 和 popf,为直接访问标志寄存器提供了一种方法。

笔记

8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW)
本章中的标志寄存器(以下简称为flag)是我们要学习的最有一个寄存器
flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息
8086CPU的flag寄存器的结构:
    1.flag的1、3、4、12、13、14、15位共7位在8086CPU中没有使用,不具有任何含义
        而0、2、4、6、7、8、9、10、11位共9位都具有特殊的含义
    2.示意图

11.1 ZF标志
    1.flag的第6位是ZF,零标志位。
        它记录相关指令执行后,
          1.结果为0,ZF=1
          2.结果不为0,ZF=0
    2.示例:
        mov ax,1
        sub ax,1
        指令执行后,结果为0,则ZF=1
        mov ax,2
        sub ax,1
        指令执行后,结果不为0,则ZF=0
    3.注意,在8086CPU的指令集中,有的指令的执行会影响标志寄存器
        比如:add、sub、mul、div、inc、or、and等
        他们大都是运算指令(逻辑运算或者算术运算)
      有的指令的执行对标志寄存器没有影响,
        比如:mov、push、pop等,他们大都是传送指令
11.2 PF标志
    flag的第2位是PF,奇偶标志位
    它记录指令执行后,结果的所有二进制位中1的个数
      1.为偶数,PF=1
      2.为奇数,PF=0
11.3 SF标志
    1.flag的第7位是SF,符号标志位
    2.它记录指令执行后
      1.结果为负。sf=1
      2.结果为正,sf=0
      sf标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负
        sf标志把所有数当作有符号数
        如果把数据当作无符号数运算,sf的值则没有意义,虽然相关指令会影响它的值
    3.也就是说,CPU在执行add等指令时,是必然要影响sf标志位的值
        至于我们需不需要这种影响,那就看我们如何看待指令所进行的运算    
11.4 CF标志   
    1.flag的第0位是CF,进位标志位
      一般请况下,在进行无符号数运算的时候,
        它记录了运算结果的最高有效位向更高位的进位值,
          或从更高位的借位值
        代表假想的更高位
    2.CPU在运算时,不会丢弃进位值,而是记录在一个特殊的寄存器的某一位上
        8086CPU就用flag的cf为来记录这个进位值,借位也一样
    3.在debug中的显示

    4.无符号的时候产生的结果
11.5 OF标志
    flag中的第11位
    进行有符号数运算的时候,如果结果超过了机器所能表示的范围称为溢出
    1.这里所讲的溢出,只是对有符号数运算而言
      就像进位只是相对于无符号数而言!
    2.一定要注意cf和of的区别
        当需要把机器码看成有符号数则使用of
        当需要把机器码看成无符号数则使用cf
11.6 adc标志
    adc是带进位的加法指令,他利用了cf上记录的进位值
    1.格式:adc 操作对象1,操作对象2
    2.功能:操作对象1=操作对象1+操作对象2+cf
      比如:adc ax,bx实现的功能是:
        (ax)=(ax)+(bx)+cf
    3.执行adc指令的时候,加上的cf的值的含义,由adc指令前的指令决定
        也就是说,关键在于所加上的cf值是被什么指令设置的
    4.如果cf是被sub指令设置的,那么他的含义就是借位值
      如果是被add指令设置的,那么它的含义就是进位值
    5.下面的指令和add ax,bx具有相同的结果
        add al,bl
        adc ah,bh
        CPU提供adc指令的目的,就是来进行加法的第二步运算的
        adc指令和add指令相配合就可以对更大的数据进行加法运算
    【实验:编程计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中】
11.7 sbb标志
    sbb是带借位减法指令,他利用了cf位上记录的借位值
    1.格式:sbb 操作对象1,操作对象2
    2.功能:操作对象1=操作对象1-操作对象2-cf
    3.利用sbb指令,我们可以对任意大的数据进行减法运算
    4.sbb和adc是基于相同的思想设计的两条指令,
        在应用思路上和adc类似
11.8 cmp标志
    1.cmp是比较指令,功能相当于减法指令,只是不保存结果
    2.cmp指令执行后,将对标志寄存器产生影响
    3.其他相关指令通过识别这些被影响的标志寄存器,来得知比较结果
    4.cmp指令格式:cmp 操作对象1,操作对象2
    5.功能:计算操作对象1-操作对象2,但并不保存结果,仅仅根据计算结果对标志寄存器进行设置
    6.比如:cmp ax,ax
        做(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关位
        指令执行后
        zf=1    ;结果为0
        pf=1    ;结果的1的个数为偶数
        sf=0    ;结果为正号
        cf=0    ;结果没有产生进位或借位
        of=0    ;结果没有溢出
    7.根据flag,判断cmp指令的结果(无符号数)

    8.cmp既可以对无符号数进行比较,也可以对有符号数进行比较
        cmp 操作数1,操作数2   ;操作数1、操作数2都是有符号数
        1.of=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负
            of=0,sf=1   则 操作数1比操作数2小
            of=0,sf=0   则 操作数1比操作数2大
        2.of=1,说明有溢出,逻辑上真正结果的正负与实际结果的正负相反
            of=1,sf=1   则 操作数1比操作数2大
            of=1,sf=0   则 操作数1比操作数2小
11.9 检测比较结果的条件转移指令
    1.这些条件转移指令通常和cmp相配合使用
    2.因为cmp指令可以同时进行两种比较,无符号数和有符号数的比较
      所以,这些转移指令也分为两种,即:
        1.根据【无符号数】的比较结果进行转移的条件转移指令,
          他们检测zf、cf的值
        2.根据【有符号数】的比较结果进行转移的条件转移指令
          他们检测sf、of和zf的值
    3.无符号比较,条件转移指令小结【无符号,6个】
      1.je  等于则转移     zf=1
      2.jne 不等于则转移   zf=0
      3.jb  低于则转移     cf=1      【b表示below】
      4.jnb 不低于则转移   cf=0
      5.ja  高于则转移     cf=0,zf=0【a表示above】
      6.jna 不高于则转移   cf=1或zf=1
11.10 DF标志和串传送指令
    1.flag的第10位DF,方向标志位
        在串处理指令(movsb,movsw)中,控制每次操作后si、di的增减
        df=0:每次操作后si,di递增
        df=1:每次操作后si,di递减
    2.格式:movsb
    3.功能:(以字节为单位传送)
        1.((es)*16+(di))=((ds)*16+(si))
        2.如果df=0,则:(si)=(si)+1
                       (di)=(di)+1
          如果df=1,则:(si)=(si)-1
                       (di)=(di)-1
        3.功能文字描述
            movsb的功能是将ds:si指向的内存单元中的字节
            送入es:di中,然后根据标志寄存器df位的值,
              将si和di递增或递减
    4.movsw 传送一个字
    5.movsb和movsw都和rep配合使用
        格式:rep movsb
        rep的作用根据cx的值,重复执行后面的串传送指令
    6.cld指令和std指令
        cld指令:将标志寄存器的df置为0【c:clear】
        std指令:将标志寄存器的df置为1【s:set】
11.11 pushf和popf
    pushf:将标志寄存器的值压栈
    popf:从栈中弹出数据,送入标志寄存器中
    pushf和popf为直接访问标志寄存器提供了一种方法
11.12 标志寄存器在debug中的表示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值