前言:在学习汇编的时候,对于标志寄存器的一些地方有些不懂,或不是太熟悉,因此打算自己写一个关于标志寄存器的总结。
首先说一下标志寄存器的概念。在8086cpu中标志寄存器都是16位的,而其中存储的信息被称为程序状态字(一段包含系统状态的内存或者是硬件区域)。标志寄存器既然是寄存器,那么它也是用来存储信息的,只是它存储信息的方式与其他的寄存器不同而已。其他的寄存器是一个寄存器包含一个信息,而标志寄存器则可以包含多个信息。而标志寄存器之所以可以存储多个信息,是因为它的存储方式。在标志寄存器中,信息是被存储在位中的。标志寄存器中的每一个位都可以代表特定的信息。
这是我在网上找的一个标志寄存器的示意图。通过这张图片我们可以知道在标志寄存器中,哪些是用到的,哪些是没用到的。我就不在赘述了。接下来我们看一下这些位的具体含义。
CF(carry flag):进位标志位。这个位是在进行无符号数运算的时候用到的。一般情况下,这个位记录了进行无符号运算的时候,运算结果的最高有效位向更高位的进位值,或从更高位的借位值。注意的是,这里的进位与借位,都是相对于二进制而言的。下面我们再找一张图来加深下理解。
PF(parity flag):奇偶标志位。这个位的判断需要我们将结果转为二进制来看,如果结果的低8位中有偶数个1,就将PF的值置1;如果是奇数个1,就置0。要注意的是一定是结果的低8位。
AF(auxiliary flag):辅助进位标志位。这个位用的不多,所以书上也没有讲,我就简单的查了一下资料。这个位表示加减法做到一半时有没有形成进位/借位,如果有则AF=1。这么说谁都听不懂,所以我们举个例子来说下。例如 MOV AL,00001110 MOV BL,00001000 ADD AL,BL 最后结果为AL=00010110这就是低四位向高四位进位。反之在减法中第三位不够减向第四位借位(注意数位是从第0位开始数的)叫低四位向高四位借位!像前面的AL中前四位为高四位,后四位为低四位。例如,当两个字节相加时,如果从低4位向高4位有进位时,则AF=1。
ZF(zero flag):零标志位。这个位就很简单了,判断结果是不是0。如果结果为0,就置1;不为0,就置0。
SF(sign flag):符号标志位。既然是符号标志位,就是对有符号数据来说的。如果结果为负,就置1;结果为正,就置0。
TF(timer overblow flag):定时器溢出标志。这个位主要是用来在debug中进行-t指令时使用的。当cpu在执行完一条指令后,如果检测到TF位的值为1,则产生单步中断,引发中断过程。通过这个位,我们就可以在debug中对程序进行单步跟踪。
IF(interrupt flag):中断允许标志位。当IF=1时,cpu在执行完当前指令后响应中断,引发中断过程;当IF=0时,则不响应可屏蔽中断。
DF(direction flag):方向标志位。在串处理指令中,控制每次操作后,si(指向原始偏移地址)、di(指向目标偏移地址)的增减。当DF=0时,每次操作后,si、di递增;DF=1时,每次操作后,si、di递减。我们可以使用cld指令将DF的值置为0,使用std指令将DF的值置为1。DF需要与rep、movsb等指令配合使用。
OF(overflow flag):溢出标志位。这个位是用来判断有没有溢出的。注意溢出这个概念只对于有符号数据而言,就如同进位只对于无符号数据而言。当OF=0时,说明没有溢出;当OF=1时,说明溢出了。
我们再来看一下各个位在debug中是如何表示的:
标志 | debug(1/0) | |
CF | CY | NC |
PF | PE | PO |
AF | AC | NA |
ZF | ZR | NZ |
SF | NG | PL |
IF | EI | DI |
DF | DN | UP |
OF | OV | NV |
以上这些就是关于标志寄存器的基本概念了。但是光有这些概念确实不够用的,因为要学以致用,也就是做一些题。我记得我学的时候就是知道概念,但是题就是不会做。所以接下来我们做一道题来加深理解。
题目:写出下面每条指令执行后,ZF、PF、SF、CF、OF等标志位的值。 sub al,al mov al,10h add al,90h mov al,80h add al,80h mov al,0fch add al,05h mov al,7dh add al,0bh |
答案: al CF OF SF ZF PF sub al,al 0h/0000 0000b 0 0 0 1 1 mov al,10h 10h/0001 0000b 0 0 0 1 1 add al,90h a0h/1010 0000b 0 0 1 0 1 mov al,80h 80h/1000 0000b 0 0 1 0 1 add al,80h 0h/0000 0000b 1 1 0 1 1 mov al,0fch 0fch/1111 1100b 1 1 0 1 1 add al,05h 1h/0000 0001b 1 0 0 0 0 mov al,7dh 7dh/1111 1101b 1 0 0 0 0 add al,0bh 88h/1000 1000b 0 1 1 0 1 |
解析: 第一条指令:sub al,al。此时al的值为0,那么自然没有借位,也不会有溢出,不是负数,值为0,二进制中都是0,也就是0个1。 第二条指令:mov al,10h。我们只需要知道如mov、push、pop等指令不会对标志寄存器有影响就可以了。 第三条指令:add al,90h。这里就是10h+90h=0001 0000b+1001 0000b=1010 0000b=a0h。先看CF位,我们可以看到没有进位(可以自己用计算器算下,不过要调为字型数据再去算);接下来是OF位,我们将10h换为十进制有符号数据为16,90h则为-112,a0为-96。也就是16-112=-96,正确,所以没有溢出。需注意的是:首先是转换为有符号数据是计算器要是字节型数据。其次,在判断溢出时,如果答案我们算的一样,就是没有溢出,如果出现了正数+正数=负数一类的,那就是溢出了。SF位是对于有符号数据来说的,也就是-96。PF位要注意是低8位就可以(不过这里也没有高8位,而且这个考的不多,知道就好)。 第五条指令:add al,80h。80h+80h=1000 0000b+1000 0000b=0000 0000b(0001 0000 0000b)=0h(100h)。我们知道al是字节型的,只可以存储8。通过上边的式子我们也可以很明显的看出存在进位的现象。所以如果用计算器(字节型)算的话就是0,如果是用字型计算器算的话就是另一个结果,因此CF=1。80h对应的无符号数据是-128,最后的结果为(-128)+(-128)=0。负数加负数为0,肯定是溢出了。其他省略了。 第七条指令: add al,05h。0fch+05h=1111 1100b+0000 0101b=0000 0001b(1 0000 0001b)=1h(101h)。有符号运算(-4)+5=1。所以有进位,没有溢出。 第九条指令:add al,0bh。7dh+0bh=0111 1101b+0000 1011b=1000 1000b=88h。有符号运算120+5=(-120)。所以无进位,有溢出。 |
关于计算器,如果你设置为字节型的,那么得到的就是有符号数据,如果是字型的,就是无符号数据。
在往寄存器中存储数据的时候,是以二进制的形式往里面存储数据的。
如果有错误的地方,欢迎指正!