• 从0开始学汇编第二天:寄存器(CPU工作原理)


    一个典性的CPU由运算器、控制器、寄存器等器件构成,这些器件靠内部总线相连。前一章说的总线,相对于CPU内部来说是外部总线。内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。简单来说,在CPU中:运算器进行信息处理;寄存器进行信息存储;控制器控制其他器件进行工作;内部总线链接各种器件,在他们之间进行数据的传送。

    1、通用寄存器

    8086CPU的所有寄存器都是16位的,可以存放两个字节。AX、BX、CX、DX四个寄存器通常用来存放一般性的数据,被称为通用寄存器。
    以AX为例,寄存器的逻辑结构如下图所示:
    在这里插入图片描述
    一个16位寄存器可以存储一个16位的数据,数据再寄存器中的存放情况如图所示。

    第一个问题:一个16位寄存器所你能存储的数据的最大值为多少?(2^16-1=65535)

    8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,使原来基于上代CPU编写的程序稍加修改就可以运行在8086之上,8086CPU的AX、BX、CX、DX四个寄存器都可分为两个独立使用的8位寄存器来用:

    • AX可分为AH和AL;
    • BX可分为BH和BL;
    • CX可分为CH和CL;
    • DX可分为DH和DL;

    数据:18
    二进制表示:10010
    在寄器AX中的存储:
    在这里插入图片描述

    数据:20000
    二进制表示:100111000100000
    在寄存器AX中的存储:
    在这里插入图片描述
    以AX为例,8086CPU的16位寄存器分为两个8位寄存器的情况如图所示:
    在这里插入图片描述
    AX的低8位(0位~7位)构成了AL寄存器,高8位 8位~15位)构成了AH寄存器。AH和AL寄存器是可以独立使用的8位寄存器。下图膳食了16位寄存器及他所分成的两个8位寄存器的数据存储的情况。

    在这里插入图片描述

    第二个问题:一个8位寄存器所能存储的最大值为多少?(2^8-1 = 255)

    2、字在寄存器中的存储

    出于对兼容性的考虑,8086CPU可以一次处理两种尺寸的数据:

    • 字节:记为Byte,一个字节由8个比特(即二进制位)组成,可以存在8位寄存器中
    • 字:即为Word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节,如所示:
      -
      一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。
      如图:
      一个字型数据20000,存在AX寄存器中,在AH中存储了他的高8位,在AL中存储了他的低8位。AH和AL中的数据,既可以看成是一个字型数据的高8位和低8位,这个字型数据的大小是20000;又可以看成是两个独立的字节型数据,他们分别是78和32.
      在这里插入图片描述
    3、几条汇编指令

    我们可以通过汇编指令控制CPU进行工作,常用指定如表所示:

    汇编指令控制CPU完成的操作用高级语言的语法描述
    mov ax,18将18送入寄存器AXAX = 18
    mov ah,78将78送入寄存器AHAH= 78
    add ax,8将寄存器AX中的数值加上8AX=AX+8
    mov ax,bx将寄存器BX中的数据送入寄存器AX中AX=BX
    add ax,bx将AX和BX中的数值相加,结果存在AX中AX=AX+BX

    注意:为了具有高级语言基础的读者更好地理解指令的含义,有时会用文字描述和高级语言描述这两种方式来描述一条汇编指令的含义,在写一条汇编指令或一个寄存器的名称时并不区分大小写,如:mov ax,18和MOV AX,18的含义相同,BX和bx的含义相同

    在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的,例如:
    在这里插入图片描述
    而第二部分都是错误的指令,错误的原因是指令的两个操作对象的位数不一样。

    检测

    在这里插入图片描述

    4、物理地址

    CPU访问内存空间时,要给出内存单元的地址。所有的内存单元构成存储空间是一个一维的线性空间,每一个内存空间在这个空间中都有唯一的地址,我们将这个唯一的地址称为物理地址。

    CPU通过地址总线送入存储器的必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须在内部先形成这个物理地址。不同的CPU可以有不同的形成物理地址的方式。

    5、16位结构的CPU

    我们说8086CPU的上一代CPU(8080、8085)等是16位机,也可以说8086时16位结构的CPU。

    概括地讲,16位机构(16位机、字长为16等常见说法,与16位机构的含义相同)描述了一个CPU具有下面几方面的机构特征:

    • 运算器一次最多可以处理16位的数据;
    • 寄存器的最大宽度为16位
    • 寄存器和运算器之间的通络为16位
      8086是16位结构的CPU,这也就是说,在8086内部,能够一次性处理、传输、暂时存储的信息的最大长度是16位的。内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放,对于16位CPU,能一次性处理、传输、暂时存储16位的地址。
    6、8086CPU给出物理地址的方法

    8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力。8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。从8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64 KB。

    8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。

    8086CPU相关部件的逻辑就构图如图所示:
    在这里插入图片描述

    如图2.6所示,当8086CPU要读写内存时:
    (1) CPU 中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;

    (2)段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;

    (3)地址加法器将两个16位地址合成为一个20位的物理地址;

    (4)地址加法器通过内部总线将20位物理地址送入输入输出控制电路;

    (5)输入输出控制电路将20位物理地址送上地址总线;

    (6)20位物理地址被地址总线传送到存储器。

    地址加法器采用物理地址=段地址×16+偏移地址的方法用段地址和偏移地址合成物理地址。例如:8086CPU 要访问地址为123C8H的内存单元,此时,地址加法器的工作过程如图所示(图中数据皆为十六进制表示)。

    在这里插入图片描述
    在这里插入图片描述

    7、“段地址×16+偏移量=物理地址”的本质含义

    “段地址×16+偏移地址=物理地址”的本质含义是:CPU在访问内存时,用一个基础地址(段地址×16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。

    更一般地说,8086CPU的这种寻址功能是“基础地址+偏移地址=物理地址”寻址模式的一-种具体实现方案。8086CPU 中,段地址×16可看作是基础地址。
    下面,我们用两个与CPU无关的例子做进一步的比喻说明。第一个比喻说明“基础地址+偏移地址=物理地址”的思想:

    比如说,学校、体育馆、图书馆同在一条比直的单行路上(参考图2.8),学校位于路的起点(从路的起点到学校距离是0米)。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    8、段的概念

    我们注意到,“段地址”这个名称中包含着“段”的概念。这种说法可能对一些人产生了误导,使人误以为内存被划分成了一个一个的段,每一个段有一个段地址。如果我们在一开始形成了这种认识,将影响以后对汇编语言的深入理解和灵活应用。
    其实,内存并没有分段,段的划分来自于CPU,由于8086CPU用“基础地址(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。如图2.9所示,我们可以认为:地址10000H~100FFH的内存单元组成一个段,该段的起始地址(基础地址)为10000H,段地址为1000H,大小为100H;我们也可以认为地址 10000H1007FH、10080H10OFFH 的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和100080H,段地址为:1000H和1008H,大小都为80H。
    在这里插入图片描述
    以后,在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。有两点需要注意:段地址×16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址为16位,16位地址的寻址能力为64 KB,所以一个段的长度最大为64 KB。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    9、段寄存器

    我们前面讲到,8086CPU在访问内存时要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址。这里,我们要看一下,是什么部件提供段地址。段地址在8086CPU 的段寄存器中存放。8086CPU有4个段寄存器:CS、DS、SS、ES。当8086CPU要访问内存时由这4个段寄存器提供内存单元的段地址。我们本课中只介绍CS。

    10、CS和IP

    CS 和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前要读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器,从名称上我们可以看出它们和指令的关系。

    在8086PC机中,任意时刻,设CS 中的内容为M,IP 中的内容为N,8086CPU 将从内存M×16+N单元开始,读取一条指令并执行。

    也可以这样表述:8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。图2.10展示了8086CPU读取、执行指令的工作原理(图中只包括了和所要说明的问题密切相关的部件,图中数字都为十六进制)。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    11、修改CS、IP的指令

    在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对CPU的控制。CPU从何处执行指令是由CS、IP中的内容决定的,程序员可以通过改变CS、IP中的内容来控制CPU执行目标指令。

    我们如何改变CS、IP的值呢﹖显然,8086CPU必须提供相应的指令。如何修改AX中的值?可以用mov指令,如: mov ax,123将ax 中的值设为123,显然,也可以用同样的方法设置其他寄存器的值,如 : mov bx,123, mov cx,123, mov dx,123等。其实,8086CPU大部分寄存器的值,都可以用mov指令来改变,mov指令被称为传送指令。

    但是,mov指令不能用于设置CS、IP的值,原因很简单,因为8086CPU没有提供这样的功能。8086CPU为CS、IP提供了另外的指令来改变它们的值。能够改变CS、IP 的内容的指令被统称为转移指令(我们以后会深入介绍)。我们现在介绍一个最简单的可以修改cS、IP的指令: jmp指令。

    若想同时修改CS、IP的内容,可用指令“jmp段地址:偏移地址”完成,如:jmp 2AE3:3,执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令。jmp 3:0B16,执行后:CS=0003H,IP=0B16H,CPU将从00B46H处读取指令。jmp段地址:偏移地址指令的功能为:用指令中给出的段地址修改CS,偏移地址修改IP。
    若想仅修改P的内容,可用指令“jmp某一合法寄存器”完成,如:jmp ax,指令执行前: ax=1000H,CS=2000H,IP=0003H
    指令执行后: ax=1000H,CS-2000H,IP=1000H
    jmp bx,指令执行前: bx=0B16H,CS=2000H,IP=0003H
    指令执行后: ax=OB16H,CS=2000H,IP=OB16H
    指令“jmp 某一合法寄存器”的功能为:用寄存器中的值修改IP。jmp ax,在含义上类似于mov lP,ax这样的指令。

    注意:
    采用一种“用汇编解释汇编”的方法来使读者更好地理解汇编指令的功能,这样做有助于读者进行知识的相互融会。要强调的是,我们是用“已知的汇编指令的语法”进行描述,并不是用“已知的汇编指令”来描述,比如:我们用mov IP,ax来描述jmp ax,并不是说真有mov IP,ax这样的指令,而是用mov指令的语法来说明jmp指令的功能.我们可以用同样的方法描述jmp 3:01B6的功能: jmp 3:01B6在含义上好似mov Cs.3mov 1P,01B6。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    12、代码段

    前面讲过,对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。可以将长度为N(N≤64 KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,从而定义了一个代码段。比如,将:
    在这里插入图片描述
    这段长度为10字节的指令,存在从123BOH123BAH的一组内存单元中,我们就可以认为,123BOH123BAH这段内存是用来存放代码的,是一个代码段,它的段地址为123BH,长度为10字节。

    如何使得代码段中的指令被执行呢?将一段内存当作代码段,仅仅是我们在编程时的一种安排,CPU并不会由于这种安排,就自动地将我们定义的代码段中的指令当作指令来执行。CPU 只认被CS:IP指向的内存单元中的内容为指令。所以,要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。对于上面的例子,我们将一段代码存放在123BOH~123BAH内存单元中,将其定义为代码段,如果要让这段代码得到执行,可设CS=123BH、IP=0000H。

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    开放式激光振镜运动控制器:C++ 快速调用图形库应用
    数据结构之堆
    【线性代数】为什么 AA* = |A|E
    Day 49 | 121. 买卖股票的最佳时机 & 122. 买卖股票的最佳时机 II
    机器学习__04__朴素贝叶斯算法
    信息论作业 P02014222 焦子阳
    MIPI CSI-2笔记(19) -- 数据格式(用户自定义数据格式)
    PHP 获取当前时间戳,精确到毫秒
    今年嵌入式行情怎么样?
    APM32F103VCT6 写内部Flash失败解决方案(亲试可用)
  • 原文地址:https://blog.csdn.net/weixin_62529383/article/details/127818179