CPU寻址方式与过程

在看了上一篇转载的文章后,自己也仔细搜索研究了下关于CPU寻址方面的东西,写下来吧。

首先,说到寻址,当然离不开各种各种总线啦,先来看下我们的计算机系统内的总线结构图啦(下图来自大话存储)

CPU寻址方式与过程_第1张图片 

如图,主板上的每个部件都是通过总线连接起来,其实,这些密密麻麻的先都是印刷在电路板上,这些线中,有一些是部件之间交互数据时候用的数据总线,有的是一些地址总线,用来确认通信时候的目标设备,一般按照数据总线的条数来确认一个总线或者设备的位宽,比如32PCI总线,则表明这条总线总有32跟导线用于数据信号的传递。CPU与北桥连接的总线叫前端总线,这个总线的传输频率域CPU的自身频率是不同的,总线频率相当于CPu向外存取数据时候的数据传输速率,而CPU自身的频率则是CPu运算时候电路产生的频率。前端总线的的条数就叫总线的位数,这个位数与CPU内粗你的位数是不同概念的(下面讲到),大话存储中说这个前端总线也叫系统总线,我觉得这是不妥的(见下面)。内存与北桥连接的总线叫做内存总线,由于北桥速度太多,而IO总线速度相对北桥西显得太慢,所以北桥与IO总线之间,往往增加一个网桥叫做南桥,在南桥上一般集成了众多外设的控制器,比如磁盘控制器,USB控制器等。

 

下面我们就来说说各个总线

 

A computer's bus can be divided into two different types, Internal and External.

The Internal Bus connects the different components inside the case: The CPU, system memory, and all other components on the motherboard. It's also referred to as the System Bus.

The External Bus connects the different external devices, peripherals, expansion slots, I/O ports and drive connections to the rest of the computer. In other words, the External Bus allows various devices to be added to the computer. It allows for the expansion of the computer's capabilities. It is generally slower than the system bus. Another name for the External Bus, is the Expansion Bus.

从这段话中,我们知道,一个计算机系统总线可以分为内部总线与外部总线,内部总线只要就是连接CPU,内存或者其他在母板上的部件,这么说的话,连接CPU与内存的前端总线只是系统总线中的一种,系统总线应该还包括其他连接内部部件例如CPU内的运算部件与cache部件这些(好像这就交后端总线)。而外部总线相当于扩展了计算机的工呢过,使得更多的设备可以接入计算机。

而外部总线也就是我们通常所说的IO总线,或者输入输出接口。

 

而从功能上来说,总线又主要分为数据线,地址线,控制线。

 data bus is a computer subsystem that allows for the transferring of data from one component to another on a motherboard or system board, or between two computers. This can include transferring data to and from the memory, or from the central processing unit (CPU) to other components. Each one is designed to handle so many bits of data at a time. The amount of data a data bus can handle is called bandwidth.

数据总线是计算机系统部件之间传输数据信息的总线,包括从内存取数据,放数据到内存中,或者是从CPU到其他部件,而每次能传输的数据位数也就是数据总线的宽度了,也叫带宽(我们一般用每秒传输多少字节来表示)。

地址总线AB是专门用来传送地址的,由于地址只能从CPU传向外部存储器或IO端口所以地址总线总是单向三态的这与数据总线不同。地址总线的位数决定了CPU可直接寻址的内存空间大小。

 

这时候问题就来了,那么他跟我们平时所说的CPU位数是否相关呢?答案是否的。(这也是我转载的上篇文章中作者极力要向大家说明的问题)

当我们说一个CPU16位,32位,是指处理器中“算术逻辑单元(ALU)”的宽度,他代表的是CPU一次能并行处理的数据位数。也叫字长。而系统总线中的数据线部分,也就是数据总线,通常与ALU具有相同的宽度。

那么地址总线宽度能,最自然的想法是与数据总线一致是最好的,而实际上这是不现实的,一般,8位的CPU的地址总线都是16位(这时候CPU的寻址能力就是216次方也就是64K)。这就造成了CPU内部结构的不均匀性,在8CPU的指令系统中常常出现一些实际上是16位的操作,也就是双字长操作。而在16CPU中,地址总线一般是20位达到1M的内存空间了。所以,CPU的位数与寻址空间是没有联系的,因为寻址空间决定于地址总线,而地址总线与CPU位数是没关系的。

 

而这时候,X80808位机,数据总线为8位,地址总线为16位。那么这个地址信息可以通过8位的数据总线传送,在数据通道中暂存,以及在cpu中的寄存器(地址寄存器)和内存中存放,因为AB刚好是DB的整数倍。

但是而在X86系列中16位机,数据总线是16位但地址总线是20位,20位的地址信息就不能再DB上传输,也不能在数据通道中暂存,以及在cpu中的寄存器(地址寄存器)和内存中存放。这时候就引出了段管理,逻辑地址,物理地址.Intel8086CPU中设置了四个段寄存器:CS DS SS ES ,分别用于可执行代码,数据,堆栈及其他,每个段寄存器都是16位的(注意,CPU位数,数据总线位数,CPU内部寄存器的位数一般都是一样的)。引入段寄存器是为了让CPU有更多的内存而又不用扩展寄存器和指令的位宽。用来告诉CPU一条程序指令将操作哪一个64K的的内存区块,解决方案就是:你先加载段寄存器,相当于说,这儿,我打算操作开始于X处的内存区块,之后再用16位 的内存地址来表示相对于那个内存区块(或段)的偏移量。

 

CPU对内存的访问是通过连接着CPU和北桥芯片的前端总线来完成的,在前端总线上传输的内存地址都是物理内存地址,编号从0一直到可用物理内存的最高端,这些数字被北桥映射到实际的内存条上,这些物理地址是明确的,最终用在总线上的编号,不必转换,但是在CPU内部,程序所用的是逻辑内存地址【段标识符:段内偏移量】,当CPU要执行一条引用了内存的指令时候,转换就开始了。每一条会访问内存的指令都隐式的使用了段寄存器。首先,将给定的一个逻辑地址(其实只是段内偏移量,这个一定要理解),CPU利用其段式内存管理单元,将LA转换为一个线性地址,如果有页式内存管理的话,再利用页式内存管理单元,转为最终的物理地址。否则第一步转化的线性地址就是实际的物理地址。这里要注意20位的实际地址的高16位对应的是段寄存器的内容,所以拿16位内部地址的高12位于段寄存器中的16位相加,而内部地址中的低四位保持不变。但是这样没有地址空间的保护机制,对于每一个由段寄存器的内容确定的基地址,一个进程能够访问从此开始的64K字节的连续地址空间,而无法加以限制,同时因为用来改变段寄存器内容的指令也不是特权指令,这样,用户可以通过改变段寄存器内的内容,一个进程就可以随心所欲的访问内存中的任何一个单元,丝毫不受限制,所以为了区别后来的“保护模式”。这种就称为“实地址模式”

针对上面说到的这个情况,于是从80386开始使用了保护模式,在保留段寄存器基础上,增加了两个段寄存器FSGS,为了实现保护模式,单用段寄存器确定一个基地址是不够的,还得需要一个地址段的长度,还需要一些其他的例如访问权限之类的,这样就需要一个数据结构而非单一的基地址了。这样,将指令中发出的地址作为位移,与段描述结构中规定的段长度比较,看看是否越界。

你可能感兴趣的:(linux内核学习及实践)