汇编语言(王爽)-标志寄存器


特殊的寄存器(不同的处理机,个数和结构可能不同)

作用:

  1. 用来存储相关指令的某些执行结果

  2. 用来为CPU执行相关指令提供行为依据

  3. 用来控制CPU的相关工作方式

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

1.png

flag的1、3、5、12、13、14、15位在8086CPU中没有使用,不具有任何含义

flag的0、2、4、6、7、8、9、10、11位都具有特殊的含义


ZF标志

flag的第6位

零标志位

用于记录相关指令执行后,其结果是否为0。

若结果为0,则ZF=1

若结果不为0,则ZF=0

8086CPU指令集中,有的指令的执行是影响标志寄存器的,如add、sub、mul、div、inc、or、and等运算指令(逻辑或算数运算);有的指令的执行对标志寄存器没有影响,如mov、push、pop等传送指令


PF指令

flag的第2位

奇偶标志位

用于记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数

若1的个数为偶数,则PF=1

若1的个数为奇数,则PF=0


SF标志

flag的第7位

符号标志位

用于记录相关指令执行后,其结果是否为负

若结果为负,SF=1

若结果不为负,SF=0

计算机中通常用补码来表示有符号数据

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

SF标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负。当数据当作有符号数来运算的时候,可通过SF来得知结果的正负;当数据当作无符号数来运算的时候,SF的值则无意义,虽然相关的指令影响了它的值


CF标志

flag的第0位

进位标志位

在进行无符号数运算时,用于记录运算结果的最高有效位向更高位的进位值,或从更高位的借位值

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

2.png

8086CPU使用flagCF位来记录进位值与借位值


OF标志

溢出

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

比如指令运算的结果用8位寄存器或内存单元来存放,那机器所能表示的范围就是-128–127,16位有符号数据,机器所能表示的范围是-32768–32767

由于在进行有符号数运算时,可能发生溢出而造成结果的错误,则CPU需要对指令执行后是否产生溢出进行记录

OF标志

flag的第11位

溢出标志位

用于记录有符号数运算的结果是否发生了溢出

若发生溢出,OF=1

若未发生溢出,OF=0

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

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

CFOF之间无任何关系


adc指令

带进位的加法指令,利用CF位上记录的进位值

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

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

例:

  1. 1
    2
    3
    4
    mov ax,2
    mov bx,1
    sub bx,ax ;(bx)=(bx)-(ax)=1-2=-1 CF=1
    adc ax,1 ;(ax)=(ax)+1+CF=2+1+1=4
  1. 1
    2
    3
    mov al,98H
    add al,al ;(al)=(al)+(al)=98H+98H=130H al中最高位1丢弃,CF=1
    adc al,3 ;(al)=(al)+3+CF=30H+3+1=34H

在执行abc指令的时候加上CF的值的含义,是由abc指令前面的指令决定的。如果CF的值是被sub指令设置的,那么CF的含义为借位值;如果CF的值是被add指令设置的,那么CF的含义为进位值

加法分为两步进行:

  1. 低位相加

  2. 高位相加再加上低位相加产生的进位值

CPU提供adc指令的目的,就是来进行加法的第二步运算的

adc指令和add指令相配合就可以对更大的数据进行加法运算

编程

计算1EF0001000H+2010001EF0H,结果放在ax(高16位)和bx(次低16位),cx(低16位)中

计算分3步:

  1. 先将低16位相加,完成后,CF中记录本次相加的进位值

  2. 再将次高16位和CF(来自低16位的进位值)相加,完成后,CF中记录本次相加的进位值

  3. 最后高16位和CF(来自次高16位的进位值)相加,完成后,CF中记录本次相加的进位值

1
2
3
4
5
6
mov ax,001EH
mov bx,0F000H ;不可直接使用字母开头的立即数
mov cx,1000H
add cx,1EF0H
adc bx,1000H
adc ax,0020H

编写子程序

对两个128位数据进行相加

名称:add128

功能:两个128位数据进行相加

参数:ds:si指向存储第一个数的内存单元,128位的数据,需要8个字单元存储,由低地址单元到高地址单元一次存放128位数据由低到高的各个字,运算结果存储在第一个数的存储空间中。ds:di指向存储第二个数的内存空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
add128:	push ax
push cx
push si
push di

sub ax,ax

mov cx,8
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

sbb指令

带借位的减法指令,利用CF位上记录的借位值

指令格式:sbb 操作对象1,操作对象2

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

sbb指令执行后,将对CF进行设置

利用sub指令和sbb指令可以对任意大的数据进行减法运算


cmp指令

比较指令

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

指令格式:cmp 操作对象1,操作对象2

功能:计算操作对象1-操作对象2,但并不保存结果,仅仅根据计算结果对标志寄存器进行设置

无符号数比较

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)不必借位,所以:CF=0(进位标志位)

(ax)>(bx),则(ax)-(bx)既不必借位,结果又不为0,所以:CF=0(进位标志位)且ZF=0(零标志位)

(ax)(bx),则(ax)-(bx)既可能借位,结果可能为0,所以:CF=1(进位标志位)且ZF=1(零标志位)

有符号数比较

cmp ah,bh

(ah)=(bh),则(ah)-(bh)=0,所以:ZF=1(零标志位)

(ah)(bh),则(ah)-(bh)≠0,所以:ZF=0(零标志位)

对于判断其他情况,并不能通过单纯的考查SF(符号标志位)来判断,必须结合查看OF(溢出标志位)来进行判断

SF=1,OF=0,则(ah)<(bh)

SF=1,OF=1,则(ah)>(bh)

SF=0,OF=1,则(ah)<(bh)

SF=0,OF=0,则(ah)(bh)


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

所有条件转移指令的转移位移都是-128–127

cmp指令可以同时进行无符号数和有符号数的比较,则根据cmp指令的比较结果进行转移的指令也分为根据无符号数的比较结果进行转移的条件转移指令(检测zfcf的值)和根据有符号数的比较结果进行转移的条件转移指令(检测sfofzf的值)

根据无符号数的比较结果进行转移的条件转移指令:

指令 含义 检测的相关标志位
je 等于则转移 ZF=1
jne 不等于则转移 ZF=0
jb 低于则转移 CF=1
jnb 不低于则转移 CF=0
ja 高于则转移 CF=0且ZF=0
jna 不高于则转移 CF=1或ZF=1

条件转移指令实质是根据所检测的相关标志位来进行条件判断是否发生转移的,与cmp指令结合使用时才会体现“等于则转移”等含义

编程

data段中的8个字节如下:

1
2
3
data segment
db 8,11,8,1,8,5,63,38
data ends

统计data段中数值为8的字节的个数,结果保存在ax中

1
2
3
4
5
6
7
8
9
10
mov ax,data
mov ds,ax
mov bx,0 ;ds:bx指向第一个字节
mov ax,0 ;重置ax,用于存放个数
mov cx,8
s: cmp byte ptr [bx],8 ;将内存单元内容与8进行比较
jne next ;不相等转向next
inc ax ;相等则ax加1
next: inc bx ;转向下一个内存单元
loop s

统计data段中数值大于8的字节个数,ax保存统计结果

1
2
3
4
5
6
7
8
9
10
mov ax,data
mov ds,ax
mov ax,0
mov bx,0
mov cx,8
s: cmp byte ptr [bx],8 ;和8进行比较
jna next ;小于8则转到next
inc ax ;大于8则ax加1
next: inc bx
loop s

统计data段中数值小于8的字节的个数,ax保存统计结果

1
2
3
4
5
6
7
8
9
10
mov ax,data
mov ds,ax
mov ax,0
mov bx,0
mov cx,8
s: cmp byte ptr [bx],8 ;与8进行比较
jnb next ;大于8转向next
inc ax ;小于8则ax加1
next: inc bx
loop s

DF标志和串传送指令

DF标志

标志寄存器第10位

方向标志位

作用:在串处理指令中,控制每次操作后SIDI的增减

DF=0:每次操作后SIDI递增

DF=1:每次操作后SIDI递减

串传送指令

movsb

格式:movsb

功能:执行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

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

movsw

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

一般来说,movsbmovsw都与rep配合使用,格式:rep movsb

rep movsb的功能:

1
2
s:	movsb
loop s

rep的作用是:根据CX的值,重复执行后面的串传送指令。由于每执行一次movsb指令sidi都会递增或递减指向后一个单元或前一个单元,则rep movsb就可以循环实现(cx)个字符的传送

类似的,rep movsw的功能:

1
s:	movsw

标志寄存器的DF位决定串传送指令执行后,sidi改变的方向,CPU提供相应的指令来对DF位进行设置

  1. cld指令:将标志寄存器的DF位置0

  2. std指令:将标志寄存器的DF位置1

编程

将data段中的第一个字符串复制到其后面的空间中

1
2
3
4
data segment
db 'Welcome to masm!'
db 16 dup (0)
data ends

使用串传送指令需提供的必要信息

  1. 传送的原始位置:data:0

  2. 传送的目的位置:data:0010

  3. 传送的长度:16

  4. 传送的方向:正向传送(向后),DF=0(sidi递增)

1
2
3
4
5
6
7
8
mov ax,data
mov ds,ax
mov si,0 ;ds:si指向data:0
mov es,ax
mov di,16 ;es:di指向data:0010
mov cx,16 ;rep循环16次
cld ;设置DF=0,正向传送(向后)
rep movsb

将F000H段最后16个字符用串传送指令复制到data段中

1
2
3
data segment
db 16 dup (0)
data ends

ds:si指向F000H段的最后一个单元,将es:di指向data段中的最后一个单元,逆向传送16个字节

  1. 传送的起始位置:F000:FFFF

  2. 传送的目的位置:data:000F

  3. 传送的长度:16

  4. 传送的方向:逆向传送(向前),DF=1(sidi递减)

1
2
3
4
5
6
7
8
9
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:000F
mov cx,16 ;rep循环16次
std ;设置DF=1,逆向传送(向前)
rep movsb

pushf和popf

pushf功能是将标志寄存器的值压栈

popf功能是从栈中弹出数据,送入标志寄存器

为直接访问标志寄存器提供了一种方法


标志寄存器在Debug中的表示

Debug中,标志寄存器是按照有意义的各个标志位单独表示的

3.png

4.png

标志位 值为1的标记 值为0的标记
OF OV NV
SF NG PL
ZF ZR NZ
PF PE PO
CF CY NC
DF DN UP

---------------The End---------------
0%