摘要:
本文首先概述了CPU在计算机系统中的重要作用,以及人们对CPU的一般认识,然后从组成原理的角度给出CPU的定义,接着重点从逻辑的角度去描述CPU,并以一个虚拟的示意性的程序CPU_CODE为载体,简述CPU的各种重要机制,目的是寻求一种更简单,更容易接受的方式去深刻的理解CPU,计算机系统,操作系统,软件设计思想等。
关键词:CPU 微程序寄存器 中断 指令系统 CPU_CODE
在PC机如此普及的今天,CPU这个名字对稍微有一点点电脑知识的人来说都不陌生,看得见也摸得着,但是对他的了解有多少呢,理解到什么程度呢,大部分人对CPU地认识基本上都停留在表面,只是知道它是计算机的大脑,控制着计算机的一切行动,不错,了解这些对计算机普通用户已经足够了,但是对于计算机的爱好者或软件开发人员,光了解这些显然是不够用的,因为有些问题没有对CPU内部机理的较深刻的理解,就解释得通,从而使你的知识体系出现断档,不能连贯和系统起来。
目前对CPU的介绍的资料主要都偏重于硬件方面,由于硬件的复杂性,对于软件人员来说经常会出现这样的情况:雄心勃勃的去找了本组成原理的书来研究CPU,结果几个电路图看下来就晕头转向了。
虽然CPU很复杂,但它肯定是可以被认知的,我们可以选取适合自己的角度去认识,理解,分析CPU。
CPU(Center Process Unit)中文名称是中央处理单元,是计算机的核心部件,CPU对整个计算机系统的运行是极其重要的,它具有如下四方面的功能:
1) 指令控制
2) 操作控制
3) 时间控制
4) 数据加工
CPU逻辑结构图如下:
算术逻辑单元 |
状态条件寄存器 |
程序计数器PC |
地址寄存器AR |
地址总线ABUS |
数据总线DBUS |
累加器AC |
存储器 |
I/O |
CPU |
|
ALU |
指令寄存器IR |
指令译码器 |
操作控制器 时序产生器 |
时钟 |
状态反馈 |
c |
c |
c |
c |
c |
缓冲寄存器DR |
(图1)
CPU由两个主要部分-----控制器和运算器组成
控制器:由程序技术器、指令寄存器、指令译码器、时序产生器和操作控制器组成。
主要寄存器:
1) 指令寄存器(IR)
2) 程序计数器(PC)
3) 地址寄存器(AR)
4) 缓冲寄存器(DR)
5) 累加寄存器(AC)
6) 状态条件寄存器
在上面的CPU逻辑图中的操作控制器是核心的核心,它是CPU所有命令的实际发起者。将操作控制器的内部逻辑展开,则CPU的整体逻辑如图2所示。
在图2中的控制存储器中,保存着CPU的指令系统的微代码实现和执行顺序控制的硬件机制。
本文不打算从硬件的角度来谈CPU的组成原理,而是从程序的角度,整体的来分析CPU的运行机理。由于CPU既有硬件实现的复杂的逻辑电路,也有程序存储的逻辑,所以我的描述CPU的运行机理的程序是虚拟的,是把软硬件逻辑高度抽象的一个表现形式,只能起到原理性的说明作用,不能实际执行,但思路与微程序控制框是一致的,是把CPU完全微程序化的结果。
程序计数器PC |
地址寄存器AR |
缓冲寄存器DR |
指令寄存器IR |
微地址寄存器μAR |
微指令寄存器μIR |
主存储器 |
控制存储器CM |
微命令 |
地址译码器 |
地址译码 |
(图2)
注:下文称CPU原理示意性程序为:CPU_CODE
代码及说明如下:
//全局变量的定义—对应着CPU固有的各种寄存器
//控制寄存器
int IP; //程序计数器
int AR; //地址寄存器
int DR; //数据缓冲寄存器
int PSW; //状态字寄存器
//段寄存器
int CS; //代码
int DS; //数据段
int ES; //附加段
int SS; //堆栈段
//指针及变址寄存器
int SP;
int BP;
int DI;
int SI;
//数据寄存器
int AX;
int BX;
int CX;
int DX;
int interrupt;//是否有中断的标志 0-无,1-有虽然CPU没有寄存器与之对应,但是它的功能在CPU中是通过硬件电路来实现的。
//主入口函数:CPU加电时,从这里开始运行
int main()
{
//全局变量的初始化,对应着硬件完成的关键寄存器的默认值
//IP=0:CS=FFF0H确定了CPU执行的第一条机器指令的物理地址,
//您是否记得,这就是BIOS ROM的入口地址,这样就可以解释
//计算机就开始执行BIOS程序的原因了。
IP=0;
CS=FFF0H;
//while循环是CPU运行状态的表现,同时也代表着操作控制器的运行逻辑。
//这个循环也是CPU运行的原动力。
while(1)
{
//取指令
getCommand();
//执行指令
execCommand();
//中断处理过程
intProcess();
}
}
//该函数主要是CPU的取指令操作的代码表示:
//CPU先将IP:CS传给AR,然后IP+1,通过AR获得指令,将指令送至指令寄存器,结束取指令的任务。
void getCommand()
{
//PC(IP)的值赋给地址寄存器
AR=IP;
//PC+1,指向下一条将要执行的指令的偏移地址
IP=IP+1;
//地址寄存器+CS段存器-->指令的物理地址
CS:IP->物理地址;
//传送指令到指令寄存器
}
//在取指令任务结束后,指令寄存器内存放着从内存中取来的等待执行的指令。
//该执行指令函数:首先将按照约定的规则通过之列的某些特殊字段,把指令转化为微程序的入口地址,然后跳转到这个微程序的函数体去执行,具体的微操作。
void execCommand()
{
//读取指令寄存器的内容,进行指令译码,根据不同的译码执行不同的微操作
switch(ConvertCode(IR))
{
case 0:
add();
break;
case 1:
sub();
break;
case 2:
mov();
break;
case 3:
in();
break;
case 4:
out();
break;
case 5:
push();
break;
case 6:
pop();
break;
default:
break;
}
}
//中断的处理过程
void intProcess()
{
if(interrupt==1)
{
//获得中断向量号
//保护中断现场,目的是可以从中断处理程序返回后继续执行
//根据中断向量号,算出中断处理程序的地址,赋值给程序计数器IP
}
}
int ConvertCode()
{
//根据特定的规则获得相应指令对应的微程序的入口地址
}
void add()
{
//加法的微程序指令
}
void sub()
{
//减法的微程序指令
}
void mov()
{
//mov微程序指令
}
void in()
{
//IN 的微程序指令
}
void out()
{
//OUT 的微程序指令
}
CPU_CODE逻辑比较简单,但却涉及到了以下几方面的原理:
1. CPU寄存器的作用:通过全局变量来诠释体现寄存器在CPU运行过程中的作用。
2. CPU取机器指令的过程:通过getCommand()函数体现。
3. CPU执行指令的过程:通过execCommand()函数体现。
4. 中断处理的过程:通过intProcess()函数体现。
5. 机器指令的译码:通过ConvertCode()函数来体现。
6. CPU指令系统:通过add(),mov()等等的函数来体现。
CPU_CODE可以理解为计算系统中任何程序的源头和实际执行者。
这需要从这几方面来说明:
首先,计算机系统中的任何程序(无论是何种语言)想要执行,最终都要被编译成机器指令并且要装入内存中。
接着,CPU_CODE从内存中取出机器指令,分析指令,执行指令,这样才真正完成一条机器指令的执行。
因为我们的程序最终是由一条条的机器指令构成的,而每一条机器指令的实际执行都是由CPU_CODE来实际执行的,进而可以说任何计算系统的程序的源头和实际执行者就是CPU_CODE.
CPU_CODE是计算机系统的动力源泉,我们经常会听说这样的字眼“CPU在不停的转”这个“转”不是就CPU_CODE这个永不推出的程序吗。
其实利用CPU_CODE的思路去理解CPU这个软硬参杂的复杂的东西,可以提炼出逻辑的主线,去除硬件对我们的干扰,加深我们对CPU,计算机系统,机器语言,操作系统等。
虽然CPU_CODE目前还是很简陋,但我相信沿着这个思路和框架对CPU_CODE进行不断的充实,我们就可以用这种方法在CPU这个什么的世界中探索到更多的秘密。
[1] 白中英,计算机组成原理,科学出版社,1999.
[2] 沈美名 温冬婵 ,IBM-PC汇编语言程序设计, 清华大学出版社,1998.