CPU和内存是计算机中两个最重要的组件。我已经知道CPU的工作原理。上一篇文章还介绍了用于内存的DRAM的存储原理。 CPU需要知道指令或数据的存储器地址,那么该地址与诸如存储器之类的硬件有何关系?现在让我们看看内存如何到达。
1.1 DRAM芯片结构

上图是DRAM芯片单元的。一个单元分为N个超级单元(可以称为单元),每个单元由M个DRAM单元组成。我们知道DRAM单元可以存储1位数据,因此描述了DRAM芯片可以存储N * M位数据。上图是一个具有16个超级单元和每个单元8位的存储模块。我们可以称其为16 * 8bit DRAM芯片。超级单元(2,1)可以矩阵形式访问,例如data = DRAM [2.1]。这样,每个超级单元都可以具有唯一的地址,这也是存储地址的基础。
每个超级单元的信息通过地址线和数据线传输,以查找和传输数据。如上图所示,有2条地址线和8条数据线连接到存储控制器(请注意,此处的存储控制器与上述北桥的存储控制器不同),并且存储控制器电路可以传输M位数据传输到DRAM芯片或从DRAM传输M位数据。为了读取或写入[i,j]超级单元的数据,存储控制器需要通过地址线传入行地址i和列地址j。在这里,我们将行地址称为RAS(行访问选通)请求,将列地址称为(列访问选通)请求。
但是我们发现地址行只有2个地址,也就是说,寻址空间是0-3。并确定一个超级单元至少需要4条地址线,那么如何实现?

解决此问题的方法是分时传输地址代码。看上图,我们可以发现DRAM芯片内部有一个行缓冲区。实际上,为了获得小区的数据,该数据被发送两次。第一次发送RAS时,会将一行数据放入行缓冲区。第二个时间段发送CAS,从行缓冲区获取数据,然后通过数据线发送出去。这些地址线和数据线通过芯片上的引脚(PIN)连接到控制电路。 DRAM电路被设计为二维矩阵,而不是线性阵列,以减少芯片上的引脚数。如上图所示,如果使用线性阵列,则需要4个地址引脚,而二维矩阵和RAS \ CAS请求方法仅需要2个地址引脚。但是这样做的缺点是增加了访问时间。
1.2个内存模块
内存模块是我们通常所说的记忆棒。购买内存时,我们经常听到我的内存使用哪种颗粒。如下左图所示,我们可以看到内存PCB上有内存颗粒。那就是我们的DRAM芯片。通过引脚与PCB连接。不同的制造商和不同类型的内存可以具有不同的大小,引脚,性能和包装,但是原理是相同的。我们将不在这里介绍。下图显示了1M * 4bit DRAM芯片的引脚图。


对于内存粒子,其容量和字长是有限的,因此在使用内存时,我们会将多个粒子组合到一个内存模块中,以扩展内存的字长和容量。当前存储器通常在存储器棒上具有多个存储器颗粒。例如,一个64M的内存可能由8个8M * 8bit SDRAM内存颗粒组成。
1.2.1个字长的数字扩展名

位扩展的方法非常简单,只需将相应的地址端,读/写控制端和多条RAM的芯片选择信号CS并行连接即可,每条RAM的I / O端可以并行输出。如上图所示,我们使用8个DRAM芯片(编号为0-7),每个超级单元存储8位数据。当获得加法(行= i,col = j)地址的数据时,请从每个DRAM芯片的单元[i,j]中取出一个字节的数据,以便传输到CPU的数据总数为8 * 8b = 64b数据我们通过8个8M * 8b内存颗粒扩展到8M * 64b内存模块。
1.2.2字存储容量扩展
RAM的字扩展是通过使用输出来控制每个RAM的芯片选择信号CS来实现的。当RAM进行字扩展时,必须增加地址线,并将增加的地址线连接到的输入作为高阶地址。同时,每个RAM的相应地址端,读/写控制端和相应的I / O端应并联。下图显示我们已经通过4个2M * 8b内存粒子将内存容量扩展到8M,字长为8位。

最后,内存通过主板上的内存插槽DIMM连接到内存总线。对于SDRAM和DDR等不同的存储器,其存储器作弊的定义是不同的。无需在此处进行详细说明。
2.内存寻址

在我们知道DRAM颗粒和存储模块如何扩展字长和容量之前,请先进行说明。内存可以是8位或64位,容量可以是1M或1G。那么如何编译内存?地址总线和计算机的字长之间是什么关系?
2.1个字长
由计算机同时处理的二进制数字组称为计算机的“字”,该二进制数字组中的位数为“字长”。 。通常,将处理8位数据的CPU称为8位CPU。一个32位CPU正在同时处理字长为32位的二进制数据。因此,这里的单词不是我们所理解的双字节(Word),而是与硬件相关的概念。一般来说,计算机数据线的位数和字长是相同的。通过这种方式从内存中获取数据后,所有数据只能传输到CPU一次。
2.2地址总线
我们已经介绍了地址总线的功能。地址总线的数量决定了他的最大寻址范围。目前,通用地址总线首先具有相同的字长。例如,一台32位计算机具有32条数据线和32条接地线,最大寻址范围为4G(0x00000000〜0xFFFFFFFF)。当然,也有例为64M,每个内存地址可以存储32位数据。按半字寻址:对于此256M存储器,其寻址范围为128M,每个存储器地址可存储16位数据。字节寻址:对于此256M内存,其寻址范围为256M,每个内存地址可存储8位数据。
对于当前的计算机,我们主要使用基于字节的寻址。因此,我们可以简单地将内存视为线性数组。数组中每个元素的大小为8位,我们称之为存储单元。这非常重要,因为稍后在内存中讨论的所有问题都以字节为单位解决。这就是为什么对于32位计算机,可以使用的最大内存容量为4GB。如果我们按字对地址进行编程,则可以使用的最大存储容量为16GB。
因此很容易想到一个问题,为什么我们要使用字节寻址?关于这个问题,我基本上没有在互联网上找到答案,甚至找不到。所以这里没有答案,为什么呢?知道麻烦的朋友告诉我。
另一个问题是,存储器寻址方法是否与DRAM芯片有关?我认为还是有一定关系的。例如,我的DRAM芯片是8M * 8bit,所以该芯片的最小存储单元是8bit,因此我们的存储器寻址不能用半个字节寻址。否则,如果您从内存中取出8位,则您不知道要将哪个4位传递给CPU。还有一种说法是,当前的DRAM芯片单元都是8位,因此它们使用字节寻址。另一方面,它也应与数据总线的位宽有关。
3.内存数据
如我们先前所知,存储器是按字节寻址的,每个地址的存储单元可以存储8位数据。我们也知道CPU通过存储器地址获得指令和数据,并将它们存储在存储单元中。现在有一个问题。我们的数据和指令不能完全是8位。如果小于8位,则没有问题,最多浪费了几位(也许字节寻址是为了节省存储空间)。但是,当数据或指令的长度大于8bit时?因为这种情况很容易发生,例如,如何将16位Int数据存储在内存中?
3. 1内存数据存储
实际上,一种简单的方法是使用多个存储单元来存储数据或指令。例如,Int16使用2个存储单元,而Int32使用4个存储单元。读取数据时,一次读取多个存储单元。因此,这里还有两个问题:
多个存储单元的存储顺序?如何确定要读取多少个存储单元?
3. 1.1大端和小端存储Little-Endian表示低字节位于存储器的低地址端,高字节位于存储器的高地址端。记忆。 Big-Endian表示高字节位于内存的低地址端,低字节位于内存的高地址端。


应注意,计算机使用的是大端存储还是小端存储由CPU确定。我们常用的X86系统CPU使用低位优先,ARM系统CPU也使用低位优先,但是某些CPU使用高位优先,例如PowerPC,Sun。确定CPU使用哪种方法很容易:
[cpp]
boolIsBigEndian(){intvlaue = 0x1234; charlowAdd = *(char *)&value; if(lowAdd == 0x12){returntrue;} returnfalse;}
由于不同的计算机具有不同的存储方法,因此不同计算机之间的交互可能需要大小转换。我们可以在Socket编程中看到这一点。我不会在这里介绍。对于我们的单个CPU,我们无需担心此转换问题。另外,我们当前的个人PC都是小端方法,因此我们以后默认使用此方法。
3. 1.2条CPU指令
我们之前已经多次提到指令的概念,并且我们也知道指令由0和1组成,汇编代码提高了机器代码的可读性。为什么在这里突然引入了CPU指令?主要是为了解释上述第二个问题,当我读取数据或指令时,如何知道需要读取多少个存储单元。
3. 1.2.1 CPU指令格式
首先,让我们看一下CPU指令的格式。我们知道CPU的质量主要是要告诉CPU该怎么做,因此CPU指令通常包含操作码(OP)和操作
操作码字段
地址代码字段
根据一条指令中操作数地址的数量,该指令可以称为几操作数指令或几地址指令。
操作代码
A1
A2
A3
三地址指令:(A1)OP(A2)-> A3
操作代码
A1
A2

两个地址指令:(A1)OP(A2)-> A1
操作代码
A1
地址命令:(AC)OP(A)-> AC
操作代码
零地址说明
A1是操作数的地址,也称为源操作数的地址; A2是操作数的地址,也称为目标操作数的地址; A3是存储结果的地址。同样,A1,A2和A3是存储器中的单元地址或算术单元中的通用寄存器的地址。因此,存在一个解决问题。指令寻址将在后面介绍。
CPU指令的设计非常复杂,因为在计算机中都保存了0和1,那么计算机如何区分指令中的操作数和操作码?如何确保指示不会重复?这不是我们讨论的重点。有兴趣的人可以阅读计算机体系结构书,其中将有介绍。从上图可以看出,CPU的指令长度是可变的。因此,CPU无法确定一条指令需要占用多少个存储单元,那么CPU如何确定一条指令是否已被读取?
3. 1.2.2命令获取
当前的CPU大多使用可变长度指令系统。键是指令的第一个字节。当CPU读取一条指令时,它不会立即读取整条指令,而是先读取该指令的第一个字节。指令分析此字节并知道它是几个字节的指令。然后依次读取以下字节。每次读取一个字节时,程序计数器PC就会增加1。读取全部指令后,PC指向下一条指令(等同于准备读取下一条指令)。
样本1:
[普通]
MOVAL,00机器代码为00000
机器码为16位,并在内存中占用2个字节:
[00000000]
[10110000]
例如,上面的MOV汇编指令将立即值00存储在AL寄存器中。 CPU获得的指令如下:
从程序计数器获取当前指令地址0x0001。存储器控制器从0x0001读取整个字节并将其发送到CPU。 PC + 1 = 0X000 2.CPU识别到[10110000],这意味着:该操作为MOV AL,并且A2为长度为1个字节的立即数,因此整个指令的字长为2个字节。 CPU从地址0x0002获取指令的最后一个字节。 CPU将立即数00存储在AL寄存器中。
这里的问题应该在步骤3中。CPU如何知道它是MOV AL的立即操作?我们在看下面的例子。

样本2:
[普通]
MOVAL,[0000]机器代码为00
这也是MOV汇编指令,整个指令需要占用3个字节。
[00000000]
[00000000]
[10100000]
我们可以比较两个指令的第一个字节之间的差,发现这里的MOV AL是1010 0000,而不是Sample1中的1011 000。 CPU读取第一个字节后,它将识别该操作为MOV AL [D16],这意味着它是寄存器间接寻址。 A3操作存储一个16位地址偏移量(为什么使用16位地址偏移量,下文将介绍),CPU将确定此指令的长度为3个字节。然后从存储器0x0002〜0x0003中读取指令的最后2个字节,对其进行寻址以找到实际的数据存储地址,然后通过CPU再次读取它,并完成操作。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-342651-1.html
一切侵略者