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)。
小总结
规律总结
情况 | SF | OF | 实际结果 | 逻辑结果 | 比较关系 |
---|---|---|---|---|---|
1 | 1 | 0 | 负数 | 负数 | (ah) < (bh) |
2 | 0 | 0 | 非负数 | 非负数 | (ah) ≥ (bh) |
3 | 1 | 1 | 负数 | 正数 | (ah) > (bh) |
4 | 0 | 1 | 非负数 | 负数 | (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中的表示