`
897371388
  • 浏览: 528542 次
文章分类
社区版块
存档分类
最新评论

读王爽老师汇编语言笔记---标志寄存器和内中断

 
阅读更多

2013-7-13 9:57:58
cou内部的寄存器中,有一种特殊的寄存器(对于不同的处理器,个数和结构都可能不同)具有三种作用:
1、用来存储相关指令的某些执行结构
2、用来为cpu执行相关执行提供行为依据
3、用来控制cpu相关工作方式
这类特殊的寄存器在8086cpu中被称为标志寄存器。8086cpu的标志寄存器有16位,其中存储的信息通常
被称为程序状态字(PSW)。
flag和其他寄存器不同,其他都是用来存放数据的,都是整个寄存器具有一个含义,但是flag寄存器是
按位起作用,每一位都有专门的含义,记录特定的信息,
8086cpu的 flag寄存器的结构图:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OF DF IF TF SF ZF AF PF CF


1 ZF标志, 零位标志位
flag的第六位标志,它记录相关指令执行后,其结果 是否为0,
如果执行结果为0 ,则ZF = 1, 否则为 0

2 PF标志, 奇偶标志位
flag的第二位标志,它记录相关指令执行后,其结果的所有二进制中1的个数是否为偶数
如果执行结果1的个数为偶数, 则 PF = 1, 否则 PF = 0;

3 SF标志, 符号标志位
flag的第七位标志,它记录相关指令执行后,其结果是否为负。
如果结果为负 则SF = 1, 否则为 0;
因为计算机中可以用补码来表示有符号的数据,计算机中的一个数据可以看作有符号和无符号的数据来
运算,所以 SF标志,就是cpu对有符号的运算结果的一种记录,它记录数据的正负,在我们将数据当成
有符号的计算的时候,可以通过它来得知结果的正负。如果当成无符号的数来计算,SF值则没有意义,
虽然执行指令有可能会影响它的值

4 CF标志, 进位标志位

flag的第零位标志, 它记录相关指令执行后,运算结果的最高有效位向更高的进位值,或从更高位的借
位值。在一般情况下,在进行无符号数据运算的时候,它记录了运算结果高有效位向更高的进位值,或
从更高位的借位值。
当两个数据相加的时候,有可能产生从最高有效位向更高位的进位,由于这个进位制可能在8位中无法保
存,所以cpu在运算的时候,就记录在这个标志位上,当然,当两个数据相减的时候,也有可能产生从最
高有效位向更高位的借位,同理flag的cf标志位也会记录这个借位值

5 OF标志,溢出标志位
flag的第十一位标志,它记录相关指令执行后,其结果是否产生溢出(当然这里所将的溢出针对有符号数
据的运算),由于在进行有符号的数据运算的时候,可能发生溢出而造成结果的错误,则cpu需要对指令

执行后是否产生溢出进行记录
如果发生溢出, 则 OF = 1 ,否则 OF = 0
一定要注意CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志
位,

adc指令
adc是带进位加法指令,它利用了CF位上记录的进位值
指令格式:adc 操作对象1,操作对象2
功能: 操作对象1 = 操作对象1+操作对象2 +CF
比如指令 adc ax,bx实现的功能是 (ax) = (ax)+(bx)+ CF
例如:
mov ax, 2
mov bx, 1
sub bx, ax //指令操作后, CF = 1

adc ax, 1
执行后 (ax) = (ax)+1 +CF = 4


在执行adc指令的时候加上CF的值的含义:由adc指令前面的指令决定的,也就是说,关键在于所加上的
CF值是被什么指令设置的,显然如果CF的值被sub设置,就是说借位,如果是add设置就是进位
cpu提供adc指令的目的,就是来进行加法的第二步运算,adc指令和add指令配合就可以对更大的数据进
行加法运算。

sbb指令
sbb是带借位减法指令,它利用了CF位上记录的借位值
指令格式 sbb 操作数1 ,操作数2
功能: 操作数1 = 操作数1 - 操作数2 - CF
比如指令 sbb ax, bx, 实现的功能(ax) = (ax) - (bx) - CF
对于sbb指令,同adc是基于同样的思想设计的两条指令,在应用上思路和adc类似。

cmp指令
cmp是比较指令 ,相当于减法功能,只是不会对结果进行保存,cmp执行后,将对标志位寄存器产生影响
,其他相关指令通过识别这些被影响的标志寄存器来得知比较结果

cmp指令格式:cmp 操作对象1,操作对象2
功能:计算操作对象1- 操作对象2但是不保存运算结果,仅仅根据计算结果对标志寄存器进行设置

cmp ah, bh为例 总结一下cpu执行cmp指令后,SF和OF的值是如何来说明比较的结果的:
(1) 如果SF = 1,而OF = 0;
OF = 0,说明没有溢出,逻辑上真正结果的正负 = 实际结果的正负
因为SF = 1,实际结果为负数,所以逻辑上真正结果为负, 所以(ah) < (bh)
(2) 如果SF = 1, OF = 1;
OF=1 ,说明有溢出,逻辑上真正的结果正负≠实际结果的正负
因为SF = 1, 实际结果为负数,而又有溢出,这说明是由于溢出导致了实际结果为负,简单分析下,
就可以看出: 如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。
这样SF = 1, OF=1 ,说明(ah) > (bh)
(3)如果SF=0,而OF = 1
OF= 1,说明有溢出,逻辑上真正结果的正负 ≠实际结果的正负
因为SF =0,实际结果非负,而OF =1 ,说明有溢出,则结果非0,所以实际结果为正
实际结果为正,而又有溢出,这说明是由于溢出导致了实际结果非负,简单分析下,就可以看出,
如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负。
这样 SF = 0 ,OF = 1, 说明(ah) < (bh)
(4)如果SF = 0, OF = 0;
OF = 0 说明没有溢出,逻辑上结果正负 = 实际结果的正负
因为SF = 0,实际结果非负,所以逻辑上真正结果非负 所以(ah) > (bh)


检测比较结果的条件转移指令
“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP
比如:jcxz就是一个条件转移指令,它可以检测cx中的值,如果(cx) = 0,就修改IP,否则什么也不做,
而且所谓的条件转移都是[-128, 127]
cpu提供的其他条件转移指令,大多数条件转移指令都检测标志寄存器的相关标志位,根据检测的结果来
决定是否修改IP。这些条件转移指令通常都和cmp相配合使用,就好像call和ret指令通常想配合使用一
样。
因为cmp指令可以同时进行两种比较,无符号数比较和有符号数比较,所以根据cmp指令的比较结果进行
转移指令也分为两种:根据无符号书数的比较结果进行转移的条件转移指令,它们检测ZF,CF的值,和
根据有符号数的比较结果进行转移的条件转移指令,它们检测SF,OF,ZF的值


DF标志和串传送指令
flag的第10位是DF,在串处理指令中,控制每次操作后si,di的增减。
DF = 0 每次操作后si,di递增
DF = 1 每次操作后si,di递减


格式 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 ;
pushf和popf
pushf的功能是将标示寄存器的值压入栈,而popf是从栈中弹出 数据,送入标志寄存器中。
可以直接访问标志寄存器。


内中断
任何一个通用的cpu,譬如8086都具备一种能力,可以在执行当前正在执行的指令之后,检测到从cpu外
部发送过来的或内部产生的一种特殊信息,并且可以立即对所接收到的信息进行处理,这种特殊的信息
,我们可以称为其:中断信息。中断的意思是指:cpu不再接着(刚执行完的指令)向下执行,而是转去执
行这个特殊信息
中断信息:只是为了方便理解而采取的一种逻辑上说法。"中断信息"是要求cpu马上进行某种处理,并
所要进行的该种处理提供了必备的参数的通知信息。

内中断的产生
对于8086cpu来说,当cpu内部有下面的情况发生时,将产生对应的中断信息:
1、除法错误,比如:执行div指令产生的除法溢出
2、单步执行
3、执行int0指令
4、执行int指令


四种不同的信息, 就会有不同的处理,cpu首先要知道,所接收到的中断信息的来源。所以中断信息中
必须包含识别来源的编码。8086cpu用称为中断类
型码的数据来标识中断信息的来源。中断类型码为一个字节型数据。


中断处理程序
cpu 接收到中断信息后,应该转去执行该中断信息的处理程序。8086cpu若要执行某处的程序,就要将CS
:IP指向它的入口, 所以必须在中断信息和其处理程序的入口地址之间建立某种联系,使得cpu根据中
断信息可以找到要执行的处理程序
我们知道中断信息中包含有标识中断源的类型码。根据cpu的设计,中断类型码的作用就是用来定位中断
处理程序。


中断向量表
cpu用8位的中断类型码通过中断向量表找到相应的中断处理程序入口地址。中断向量表就是中断向量的
列表,所谓中断向量,就是中断处理程序的入口地址,也就是说中断向量表就是中断处理程序入口地址
的列表。

中断过程
通过中断类型码在中断向量表中找到中断处理程序的入口。找到这个入口地址的最终目的是用它设置CS
和IP,使cpu完成中断处理程序.

cpu在执行完中断处理程序后,应该返回原来的执行点继续执行下面的指令。所以在中断过程中,在设置
CS:IP之前,还要将原来的CS和IP的值保存起来。在使用call指令调用子程序时有同样的问题,子程序执
行后还要返回原来的执行点继续执行,所以call指令先保存当前CS的IP值,然后在设置CS和IP。

8086cpu在收到中断信息后,所引发的中断过程:
1、从中断信息中取得中断类型码
2、标志寄存器的值入栈(因为在中断过程中,要改变标志寄存器的值,所以先将其保存在栈中)
3、设置标志寄存器的第8位TF和第9位IF的值为0,
4、CS的内容入栈
5、IP的内容入栈
6 从内存地址为 中断类型码*4和中断类型码*4 +2 的两个字单元中读取中断处理程序入口地址设置IP和CS

中断处理程序
由于cpu随时都有可能检测到中断信息,也就是说,cpu随时都可能执行中断处理程序,所以中断处理
序必须一直存储在内存某段空间之中,而中断处理程序的入口地址,即中断向量,必须存储在对应的中

断向量表表项中
编写 中断处理程序一般步骤:
1 保存用到的寄存器
2 处理中断
3 恢复用到的寄存器
4 用iret指令返回
iret指令通常和硬件自动完成的中断过程配合使用!


响应中断的特殊情况
一般情况下,cpu在执行完当前指令后,如果检测到中断信息,就响应中断,引发中断过程。可是在有些
情况下,cpu在执行完当前指令后,即使发生中断也不会响应。
如 在执行完向ss寄存器传送数据指令后,即便发生中断,cpu也不会响应。
这样做的主要原因是 SS:SP联合指向栈顶,而对它们的设置应该连续完成,如果在执行完设置ss的指令
后,cpu响应中断,引发中断过程,要在栈中压入标志寄存器、CS和IP的值,而ss改变,sp并没有改变,
ss:sp指向的不是正确的栈顶,将引发错误,所以cpu在执行完设置ss的指令后,不响应中断。这给连续
设置ss和sp,指向正确的栈顶提供了一个时机。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics