加载中…
个人资料
老徐
老徐
  • 博客等级:
  • 博客积分:0
  • 博客访问:817,838
  • 关注人气:156
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

8086 CPU 寄存器简介(3)

(2012-07-26 10:04:28)
标签:

8086

寄存器

cpu

it

分类: NSN_BspDriver

DS 寄存器和 ES 寄存器:

DS  寄存器和  ES  寄存器都属于段寄存器,其实它们和  CS  寄存器以及  SS  寄存器用起来区别不大,

既然是段寄存器的话,自然它们存放的就是某个段地址了 。

通过上面对基础知识的介绍呢,我们已经知道,如果  CPU  要访问一个内存单元时,

我们必须要提供一个指向这个内存单元的物理地址给  CPU ,

而我们也知道在  8086  CPU  中,物理地址是由段地址左移 4  位,然后加上偏移地址形成的,

所以,我们也就只需要提供段地址和偏移地址即 OK 。

8086  CPU  呢,提供了一个  DS  寄存器,并且通常都是通过这个  DS  段寄存器来存放要访问的数据的段地址 。

DS(Data  Segment):很显然,DS 中存放的是数据段的段地址 。

但是这里不得不再点一下,那就是我们对段的支持是在  CPU  上体现的,而不是在内存中实现了段,

所以事实上我们使用的段其实是一个逻辑概念,即是我们自己定义的,

再说白了,我定义一个段,我说它是数据段那它就是数据段,我说它是代码段那么它就是代码段,

它们其实都是一块连续的内存而已,至于为什么要区分为数据段和代码段,

很明显,是用来给我们编程提供方便的,即我们在自己的思想上或者说是编码习惯上规定,

数据放数据段中,代码放代码段中 。而我们在使用数据段的时候,为了方便或者说是代码的编写方便起见,

我们一般把数据段的段地址放在  DS  寄存器中,当然,如果你硬要觉得  DS  不顺眼,那你可以换个  ES  也是一样的,

至于  ES(Extra  Segment)  段寄存器的话,自然,是一个附加段寄存器,如果再说得过分点,

就当它是个扩展吧,当你发现,你几个段寄存器不够用的时候,你可以考虑使用   ES  段寄存器,

在使用方式上,则和其他的段寄存器没什么区别 

下面看一个介绍使用  DS  寄存器的  Demo:

ASSUME CS:CODES

CODES SEGMENT
   
START:

    MOV AX,1000H
    MOV DS,AX
    MOV AL,1
    MOV BX,0
    
    MOV CX,5                    ;设计一个循环,让其循环 5 次
    s: MOV [BX],AL              ;这里 [BX] 并没有指定段地址哦
       INC AL
       INC BX
       LOOP s            
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

上面的代码所做的事情,就是循环将  1,2,3,4,5 写入到地址  1000H:0000H ,1000H:0001H,

1000H:0002H,1000H:0003H,1000H:0004H  中,

语句的执行过程如下:

首先我们来看尚未执行上述任何指令时栈中的数据情况:

image

而当循环执行完成以后,我们再来看内存  1000H:0000H 处的值:

image

在这里,我们可以看到确实达到了我们预期的效果,但是大家注意看代码:

    s: MOV [BX],AL            ;这里 [BX] 并没有指定段地址哦
        INC AL
       INC BX
       LOOP s  

这里可以看到,我们在  [BX]  中并没有给其指定段地址,而只有一个偏移地址,

但是根据我们一开始的介绍,必须要有段地址和偏移地址才能够定位内存单元,

莫非这里出问题了?

其实不是的,因为我们在最前面定义了段地址   DS  为  1000H,

当我们定义好段地址后,每一次  CPU  执行到  [BX]  时,便会自动或者说是默认的从  DS  中取值,

并且将取得的值作为段地址,因此,当  [BX]  为  0001H  时,CPU  会从   DS  中取得一个  1000H ,

由这两个一合成即可以得到正确的物理地址   1000H:0000H 。

最后还提醒一点,那就是   8086  CPU  不支持直接将一个数据送入段寄存器中,

也就是下面的做法是错误的:

    MOV DS,1000H

           

               

标志寄存器(FLAG):

前面呢,已经介绍了  8086  CPU  14 个寄存器中的 13 个了,下面我们将介绍最后一个寄存器也就是  FLAG  寄存器,

FLAG  寄存器之所以放到最后一个介绍,是因为其和其他的一些寄存器不同,像   AX,BX,CX,DX  这些寄存器来说,

它们都是用来存放数据的,当然  FLAG  中存放的也是数据啦,

呵呵,不过,AX,BX 这些寄存器中的数据是作为一个整体使用的,

最多也就分成一个  AL  和  AH  使用而已,但是在  FLAG  中,数据是按位起作用的,

也就是说,FLAG  中的每一个位都表示不同的状态,

由于一个位也就能表示  和  1 ,自然,FLAG  中的每一个位就是用来描述状态的,

而且  FLAG  寄存器中存储的信息通常又被称作程序状态字(PSW) 。

下面我给出一幅  FLAG  寄存器中各个位的示意图:

image

从上面这幅图中可以看出,FLAG  的第  个位表示的是 CF  ,第 2 个位表示的是  PF  ,与此类推 . . . . 

首先,我们来看一个列表:

image

上面的这个表怎么看呢?我们通过看下面一幅截图就知道了 。

image

从上面的标记中可以看出,从左到右依次代表   OF,DF,SF,ZF,PF,CF  标志位的值,

再通过与上面的表格相对照可以知道:

OF = 0 ;

DF = 0 ;

SF = 0 ;

ZF = 0 ;

PF = 0 ;

CF = 0  ;

至于为什么我们在  Debug  模式下,使用  命令时,只会列出这几个标志位,我菜的话是因为相对来说,

列出的这几个标志位更为常用,其他的几个标志位并不经常使用的缘故吧 。

下面我们就按不同的位来分别介绍这些位所描述的状态,以及它们代表的意义:

CF(Carry  FLag) - 进位标志(第 0 位):

CF:    进位标志是用来反映计算时是否产生了由低位向高位的进位,或者产生了从高位到低位的借位 。

if(运算过程中产生了进位或者借位)
{
        CF  =  1;
}
else
{
        CF  =  0;
}
          

PF(Parity  FLag) - 奇偶标志(第 2 位):

PF:    奇偶标志是用来记录相关指令执行后,其结果的所有的  Bit  位中  的个数是否为偶数 。

if(运算结果中 1 的个数为偶数)
{
        PF  =  1;
}
else
{
        PF  =  0;
}
      

AF(Auxiliary  Carry  FLag) - 辅助进位标志(第 4 位):

AF:    用来辅助进位标志 。

if(字节操作中发生低半个字节向高半个字节借位或者进位  ||  字操作中发生低字节向高字节借位或者进位)
{
       AF = 1;
}
else
{
       AF = 0;
}

             

ZF(Zero  FLag) – 零标志(第 6 位):

ZF:    记录的是相关的指令执行完毕后,其执行的结果是否为  0 。

if(执行的结果  ==  0)
{
       ZF = 1;
}
else
{
       ZF = 0;
}

           

SF(Sign  FLag) - 符号标志(第 7 位):

SF:    符号标志,其记录相关指令执行完以后,其结果是否为负数 。

if(运算结果为负数)
{
        SF  =  1;
}
else
{
        SF  =  0;
}
     

TF(Trap  FLag) - 追踪标志(第 8 位):

TF:    追踪标志,主要是用于调试时使用 。

if(TF  ==  1)
{
       CPU 进入单步方式;
}
     

IF(Interrupt-Enable  FLag) - 中断允许标志(第 9 位):

IF:    中断允许标志,其决定  CPU  是否能够响应外部可屏蔽中断请求(以后会做详细介绍) 。

if(IF  ==  1)
{
        CPU 能够响应外部的可屏蔽中断请求;
}
else
{
        CPU 不能够响应外部的可屏蔽中断请求;
}
            

DF(Direction  FLag) - 方向标志(第 10 位):

DF:    方向标志,其用于在串处理指令中,用来控制每次操作后  SI  和  DI  是自增还是自减 。

if(DF == 0)
{
        SI++;
        DI++;
}
else
{
        SI--;
        DI--;
}
               

OF(OverFlow  FLag) - 溢出标志(第 11 位):

OF:    溢出标志,其通常记录了有符号数运算的结果是否发生了溢出 。

if(运算发生溢出)
{
        OF  =  1;
}
else
{
        OF  =  0;
}

            

                

总结

上面呢,从最简单的开始,循序渐进的介绍了  8086  CPU  中的各个寄存器,

同时也通过一些  Demo  来列举了各个寄存器的使用,

由于写的比较基础,而且量也比较多,所以,造成博文过长了,读者需一定耐心才能看完,

写本篇博文呢,并不是说将来要用汇编去开发个什么东东,

实质上,笔者学习汇编的目的也不在此,只是因为先前在接触到底层的寄存器以及内存时,

笔者总有一丝不爽的感觉,总是感觉不得要领,所以才会开始汇编的学习,

此次推出本系列博文,本意也并不是说要学习汇编做开发,只是为了提升内功而已 。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有