6. 满足程序设计的 CPU 结构 前面给出的原型 CPU 实际只能够执行顺序结构的程序。计算机 CPU 能够替代人脑工作,需要有判断分析的功能,还要能够循环地考虑问题。这就是程序设计的分支与循环。这一部分我们将进入复杂一些的 CPU 结构设计,如果你的基础不够,就要多下一点功夫了。 6.1. 实现分支循环的计算机 判断是智能的标志,计算机能够实现程序运行的有条件跳转,就是智能的表现。本节介绍的能判断计算机可以完成数据的自动输入和地址的不连续变化,具有了一定的判断能力,能够实现跳转和循环结构的程序设计。 6.1.1. 能判断计算机的逻辑 人类进行判断要依据某种变化的信息,计算机实现判断也要依靠某种变化的标志信号,实现判断的计算机必须提供这种标志机制。 能判断计算机的结构 这里给出的电子计算机是在前面加减运算计算机的基础上改造的,它的结构如 图 6‑1 所示。为了实现程序运行中数据的输入,结构中将 EROM 换成了 RAM 。 RAM 有一条复位线 Clr 可以使所有的存储单元的值为 0 。前面的加减运算计算机只能从存储器的 0000 号单元开始执行指令,执行程序的方式只能是顺序的,不能改变顺序,不具有灵活性。这个计算机将行波计数器换成了程序计数器,目的在于能够实现程序的跳转和循环。程序计数器 PC 有 L 门,能够通过 L 门控制数据的输入,实现程序指令的不连续执行。结构中增加了输入寄存器 IN ,它可以从外部接收数据,然后送到 RAM 和其他寄存器。另外,为使该计算机有一定的判断能力,还为累加器 A 的值为 0 和为负设置了标志, A 为负数时由线 NF=1 标出, A 为 0 时由线 ZF =1 标出,这样可以根据这两条线的值实现程序的有条件跳转。 计算机控制字 显然这台简单的计算机的计算机控制字已经长了许多,由于增加了控制线,使原来的加减运算计算机的 12 位计算机控制字扩展成了 15 位: L p E p C p L m M e IOL i E i E n L a E a E u S u L b L o 由于输入寄存器 IN 的数据装入不是由控制器 CON 进行管理的,所以输入寄存器的控制线 L n 不包含在这个计算机的控制字当中。 图 6‑1 能判断计算机的结构 标志线 为了判断运算的结果,本计算机设计了判断累加器 A 中内容是 0 还是负数的识别线。 图 6‑2 中, ZF 是累加器 A 的所有数据位的或非门电路的输出端,它的值能够确定 A 中的数据是否为 0 。 NF 是累加器 A 的数据最高位的输出端,可以用它来确定 A 中的数是正数还是负数。这两条线都是为跳转指令准备的。由逻辑电路可以分析出, ZF=1 表示存放在累加器 A 中的数据是一个 0 ; NF=1 表示存放在累加器 A 中的是一个负数。可见通过 ZF 、 NF 可以知道累加器 A 的状态。 图 6‑2 标志线 定义 6‑1 能够标明设备状态的线叫 标志线 。 ZF , NF 就是标志线。标志线并不是机器的控制字,但它们是确定控制矩阵的依据,直接成为控制矩阵的自变量,属于自变量集中的元素,它们能对控制矩阵的输出端进行相应的逻辑控制。 根据标志线的定义可以知道,指令线也是标志线的一种。 计算机中的标志线一般都用 1 表示确认的状态,用 0 表示对那种状态的否定。 输入寄存器 为了使问题简单,能判断计算机结构增加了一个输入数据寄存器 IN 。输入数据寄存器 IN 的 E 门是主管向总线输送数据的,而 L 门则是主管从外部接收数据的,不受 CPU 的管理。假设输入数据寄存器 IN 的 L 门一打开就有数据进入,这些数据是事先准备好的。实际当中数据如何进入到数据寄存器,等到讲键盘缓冲区的时候再阐述。 6.1.2. 能判断计算机的指令 能判断计算机是具有条件判断功能的计算机设计,主要表现为依据一定的标志线信息,来决定后面的指令应该执行那一条。 指令的设计 根据需要,能判断计算机的指令比加减运算计算机的指令多设计了 6 个,在此将全部指令也列出一张表来说明这这些指令的设计内容(见 表 6‑1 )。 表 6‑1 指令代码设计 功 能 助记符 操作码 将数据装入当前存储单元 LOD 0000 将存储单元 R 的内容送到累加器 A LDA R 0001 将存储单元 R 的内容与累加器 A 相加,结果送累加器 A ADD R 0010 将累加器 A 与存储单元 R 的内容相减,结果送累加器 A SUB R 0011 将累加器 A 的内容送到存储单元 R STR R 0100 跳到 R 单元取指令 JMP R 0101 如果累加器 A 的值是 0 则跳到 R 单元取指令 JZ R 0110 如果累加器 A 的值为负则跳到 R 单元取指令 JN R 0111 将存储单元 R 的内容输出 OUT R 1000 读入数据并送到存储单元 R IN R 1001 停机 STP 1111 LOD 称为装入指令,它的作用是将 8 位的外部数据放入本指令所在的存储单元。由于这个地址是隐含的,故其指令格式中不要操作数。 这里把装入指令 LOD 的代码编为 0000 是因为存储器 RAM 带有 Clr 端,在开机时会将全部存储器单元的数据都变成 00000000 ,使每一个存储单元就都放置了 LOD 指令,这样通过 LOAD 可以将和存储器一样大小程序和数据一次性放入存储器。 有了指令 LOD ,在编程序时就不必用手去拨动 EROM 的开关了,可以按照存储器的形式将一条条的指令和数据书写好,放在某个外部介质上,开机时就会一次性地被读到存储器 RAM 中来,这样就能完成程序的自动输入任务。 为了能够自由地将输入数据放在指定的存储单元,这里又设计了数据输入指令 IN ,该指令可以在操作码的后面直接指出存储单元的地址,这样就可以将数据输入到 RAM 存储器的指定地方。 为了能够存放运算的结果,能判断计算机还设计了将累加器 A 的内容送到指定存储单元的指令 STR ,存储单元的地址作为操作数写在指令操作码的后面。 该计算机的结构已经使它具有逻辑判断的功能,于是就设计了两条按照一定条件改变程序执行顺序的指令,这就是有条件跳转指令 JN 和 JZ 。 JN 的意思是当累加器 A 的内容是负数时发生跳转,转移的地址由 JN 后面的操作数指出,形式是“ JN R ”。 JZ 的意思是当累加器 A 的内容是零时发生跳转,转移的地址也由 JZ 后面的操作数指出,形式是“ JZ R ”。 为了灵活地按照程序设计者的意愿进行程序执行,还设置了无条件跳转指令 JMP ,要跳转执行的下一条指令的地址由 JMP 后面的操作数指出,形式是“ JMP R ”。 条件跳转 从能判断计算机的结构可以看到,如果要改变指令的执行顺序,那么应设法将下一条要执行的指令的存储地址放在程序计数器 PC 中。根据跳转指令的格式,当跳转指令被放在指令寄存器 IR 后,就可以将 IR 的低 4 位传送给 PC 来达到跳转执行指令的目的(见 图 6‑1 )。在这个过程中,涉及到两条控制线 E i 和 L p 。如果无条件产生跳转,那么应该有 E i =1 , L p =1 。但是如果是条件转移, Ei 、 Lp 是否为 1 还要看条件,也就是 NF 和 ZF 两条标志线的具体值。 6.1.3. 指令例行程序 在加减运算计算机中已经提到过的指令,在这个能判断计算机中都有,它们的例行程序稍有变动。因为这里使用的是随机存储器 RAM ,如果需要访问 RAM ,就必须令 M e =1 ,这一点在它们的例行程序中都必须得以体现。在 EROM 的使用中没有提到块选择线 M e ,那是因为 EROM 的输出有输出控制线 E r 管理是否向总线输出, EROM 没有输入,不会引起总线数据的混乱。在块存储器组织的 RAM 中,使用时还必须要求存储器选择线 enable=1 。 为了分析和设计简单,指令可以分成几部分来研究它们的例行程序。 原指令的例行程序 加减运算计算机的指令在这个计算机中,例行程序略有变化,其中 E r 控制线变成了 M e 控制线,还有输出指令不再是将累加器 A 的内容输出,而是采用了更加灵活的将存储单元内容输出的形式。 为了使指令过程分析简化,以后值为 0 的控制线不写出,而只将值为 1 的控制线用等式表达出来。 指令 OUT R 的 例行程序如下: (1) E p =1 L m =1 (PC →MAR) (2) M e =1 L i =1 (RAM →IR) (3) C p =1 (PC+1) (4) E i =1 L m =1 (IR→MAR) (5) M e =1 L o =1 (RAM→ O ) (6) OUT R 的第 4 拍是将 指令寄存器 IR 的输出送到地址寄存器 MAR ,第 5 拍 将 RAM 的输出送到输出寄存器 O 。 新增指令的例行程序 这个计算机新增加的指令 LOD 、 JMP 、 JZ 、 JN 、 STR 、 OUT 、 IN 的例行程序仍然是 6 拍,它们的取指周期为: (1) E p =1 L m =1 (PC →MAR) (2) M e =1 L i =1 (RAM →IR ) (3) C p =1 (PC+1 ) 下面分别给出新指令例行程序的执行周期。 装入指令LOD 的执行周期 (4) M e =1 IO=1 E n =1 (IN →RAM) (5) (6) 需要指出的是,在LOD的执行周期中地址寄存器MAR的值一直都没变,故从输入寄存器读到的指令或数据,会放回LOD指令的那个存储单元。 无条件转移指令 JMP R 的执行周期 (4) E i =1 L p =1 (IR的低4位送到PC) (5) (6) A 中内容为零转移指令 JZ R 的执行周期 (4) 如果ZF=1,那么E i =1 L p =1 (A中内容为零IR的低4位送到PC) (5) (6) A 中内容为负转移指令 JN R的执行周期 (4) 如果NF=1,那么E i =1 L p =1 (A中内容为负IR的低4位送到PC) (5) (6) 指令 STR R 的执行周期 (4) E i =1 L m =1 (IR→MAR) (5) E a =1 M e =1 IO=1 (A→ RA M ) (6) 指令 IN R 的执行周期 (4) E i =1 L m =1 (IR→MAR) (5) E n =1 M e =1 IO=1 (IN→RAM) (6) IN 指令和 LOD 指令的不同之处是, LOD 指令是将数据回送到原来 LOD 指令所在的存储单元,而 IN 指令是将数据送到指令操作数所指出的那个存储单元。 6.1.4. 能判断计算机控制器 控制矩阵分组 计算机控制矩阵的设计是很复杂的,但如果新设计的计算机只是在原有的计算机中增加了设备,新增加了一些指令,并且原有的指令例行程序没有变化,那么只要设计增加的一部分指令的控制矩阵,然后将新增的控制矩阵与原控制矩阵连接。具体的连接方法,是把重复出现的控制线用或门连接,新增的控制线添加进去,这样就可以得到新设计计算机的控制矩阵。 能判断计算机的指令系统中虽然包括加减运算计算机的全部指令,然而例行程序都有一定的变化,所以不能够采用增添设计控制矩阵的方法。但为了减轻控制矩阵整体设计的压力,采用分块设计会使设计工作变得容易,并且适合多人参与的团队作战。 表 6‑2 和 表 6‑3 就是将指令分成两部分,分成 2 组的例行程序真值表,通过这两个真值表可以设计出控制矩阵的两部分。为了方便直接书写表达式,节拍前面增加一个字母“ p ”。 表 6‑2 原指令的例行程序 指令 机器动作 节拍 C p E p L m M e IO L i E i L a E a S u E u L b L o PC →MAR p1 1 1 RAM →IR p2 1 1 PC+1 p3 1 LDA R IR →MAR p4 1 1 RAM →A p5 1 1 p6 ADD R IR →MAR p4 1 1 RAM →B p5 1 1 A+B →A p6 1 1 SUB R IR →MAR p4 1 1 RAM →B p5 1 1 A -B→A p6 1 1 1 OUT R IR →MAR p4 1 1 RAM →O p5 1 1 p6 表 6‑3 新增指令例行程序 指令 机器动作 节拍 ZF NF E a C p E p L p L m M e IO L i E i E n L o PC →MAR p1 1 1 RAM →IR p2 1 1 PC+1 p3 1 JMP R IR →PC p4 1 1 p5 p6 JZ R IR →PC p4 1 1 1 p5 p6 JN R IR →PC p4 1 1 1 p5 p6 STR R IR →MAR p4 A →RAM p5 1 1 1 p6 IN R IR →MAR p4 1 1 IN →RAM p5 1 1 1 p6 LOD IN →RAM p4 1 1 1 p5 p6 控制矩阵设计 这个能判断计算机的控制矩阵完全可以像加减运算计算机那样来设计出来, 表 6‑2 表 6‑3 有底纹的部分变量属于自变量,由 表 6‑2 可得: C p =p3 E p =p1 L m =p1+p4(LDA+ADD+SUB+OUT) M e =p2+p5(LDA+ADD+SUB+OUT) L i =p2 E i =p4(LDA+ADD+SUB+OUT) L a = p5 ·LDA+p6(ADD+SUB) S u =p6 ·SUB E u =p6(ADD+SUB) L b =p5(ADD+SUB) L o =p5 ·OUT 这些函数的逻辑电路如 图 6‑3 所示。 图 6‑3 控制矩阵一组 由 表 6‑3 可得: E a =p5 ·STR C p =p3 E p =p1 L p =p4(JMP+ZF ·JZ+NF·JN) L m =p1+p4 ·IN M e =p2+p5(STR+IN)+p4 ·LOD IO= p5(STR+IN)+p4 ·LOD L i =p2 E i =p4(JMP+JZ+JN+IN) E n =p5 ·IN+p4·LOD 这些函数的逻辑电路如 图 6‑4 所示 图 6‑4 控制矩阵二组 根据逻辑等式 A+A=A 知道,以上两组逻辑函数中,完全相同的函数只在一组里表示出来即可,因而 C p 、 E p 、 L i 在后面一组中可以不必设计电路 控制器 这台能判断计算机的控制器如 图 6‑5 所示,指令译码器译出的指令线有 11 条,除去 STP 还有 10 条。 10 条指令线、 6 条节拍线和 2 条标志线,自变量共有 18 条线,其中标志线 ZF 、 NF 只对控制矩阵二组起作用。 图 6‑5 能判断计算机控制器电路 对于分组进行控制矩阵设计的方法,最后组织在一起的时候不要忘记,同名输出端要用或门组织成一个输出端。 能判断计算机控制器的工作过程,与加减运算计算机的控制器的工作过程基本一样,读者可以自己叙述整机的运行过程。 6.1.5. 跳转和循环的程序设计 能判断计算机已经有了条件跳转的指令,于是可以利用跳转指令和条件跳转指令设计一些分支程序和循环程序了。 标号和变量 前面的 例 题中,曾用括号将数值括起来表示该数值的地址,其实可以用某种标识符来表示某一个存储单元的地址。 定义 6‑2 在程序设计中表示可以存放数据的存储单元的标识符叫 变量 。 在编程中,有时仅仅是为了指明某一个暂时还不知道的存储单元的位置,这时也使用符号,这个符号后面要加上冒号以示与变量的区别。 定义 6‑3 在程序设计中,只用来指示存储单元位置的符号叫 标号 。 标号和变量在后面的汇编程序设计中经常会用到。另外,在汇编程序设计中,一般用以 “ ; ” 开始的部分来说明程序的功能,分号后面的部分是注释。 【例 6‑1 】 编程计算前 n 个自然数的和。 此 例 题可以从第 n 个自然数开始向 1 的方向求和。设置变量 N 放置自然数 n ,变量 ONE 放置 1 ,变量和 SUM 放置最后的结果, SUM 的初值是 0 。根据本计算机的指令系统写出的汇编程序如下,存储器分配如 图 6‑6 所示。 START : LDA N ;N→A JZ EXIT ;N值为0跳转 ADD SUM ;SUM+N→A STR SUM ;A→SUM LDA N ;N→A SUB ONE ;N-1→A STR N ;A→N JMP START ;循环执行求和 EXIT : OUT SUM ;输出结果 STP ;停止 这个程序先要进行编译,形成二进制代码后,才能放在存储器中执行。为了说明问题方便,这里就用汇编形式加以说明。程序和数据的存储器分配如 图 6‑6 所示,这是一个逻辑分配,实际应将二进制代码在输入设备上放置好,开机时一次性装入存储器执行。 怎样分配存储器?一般过程是先设计一个与存储器同样大小的逻辑空间,在逻辑空间上从前向后的安排每条指令,在此过程中确定标号的位置。将指令分配之后,可以在没有占用的存储单元放置数据,从而确定出变量的位置。 图 6‑6 存储器分配 程序的输入与执行 假如已经像 图 6‑6 那样安排好了二进制程序,现在如何把它放在 RAM 中执行呢?本计算机是采用如下的方法来完成的。 当电源打开之后, Clr 瞬间为 1 ,于是将各个设备进行了初始化。初始化的结果使 RAM 的每一个单元的值都是“ 00000000 ”, PC=0 ,环行计数器的值是“ 000001 ”。于是时钟启动时就开始执行 0 号单元的 LOD 指令。由于送到 MAR 的地址在后面的指令执行节拍中没变化,故读入的内容被写在 0 号单元中。此后由于 PC 自动加 1 和节拍循环的结果,使得 16 个存储单元像 图 6‑6 那样装好的程序和数据,从而完成了装填工作。当将最后一个存储单元的内容处理完成之后, PC 的值又回到了 0 ,再一次去取 0 号单元的指令,就开始执行程序了。 乘法程序 虽然这台计算机的运算器只能做加减法,但可以设计程序让它能够完成乘法和除法。 【例 6‑2 】 编程求整数 M N 的积。 仍然假定输入的数据 M 、 N 不会使结果产生溢出。乘法的问题可以用加法实现,具体思想是把 M × N 看作 N 个 M 的和。 此程序除了变量 M 、 N 之外,还要用到变量 ONE 和存放结果的变量 RESULT ,结果变量 RESULT 的初值是 0 , ONE=1 。 IN M IN N ;输入M、N LOOP : LDA N ;N→A,用N作循环计数 JZ EXIT ;若A为零,结束程序,跳转 SUB ONE ;否则,N-1→A STR N ;A→N LDA RESULT ;RESULT→A ADD M ;RESULT+M→A STR RESULT ;A→RESULT JMP LOOP ;循环执行,直到满足条件结束 EXIT : OUT RESULT ;输出结果 STP ;停止 几乎同样的编程可以求得 M/N 的结果。由 【例 6‑2 】看到只做加减法的计算机可以通过相应的程序设计,而达到实现乘除法运算。因此也就不难理解“软件是硬件的完善扩充和发展”这句话的涵义。 6.1.6. 程序流程图 在计算机编程时,人们常用流程图来说明程序的运行结构。从设计的几个汇编程序中,能够看到执行的指令之间的顺序关系基本有三种,一种是先后的顺序结构,一种是分支结构,还有一种是循环结构。 基本程序结构图 程序中的这三种结构用图来表示,就是 图 6‑7 所示形式。图中矩形框表示操作,菱形框表示条件,条件成立用“ Y ”标注,不成立用“ N ”标注,线表示流向,一般上面是入口,下面是出口。 图 6‑7 ( a )是顺序程序结构,所表达的语义是: A 操作完成之后,接着完成 B 操作。 图 6‑7 ( b )是分支程序结构,所表达的语义是:条件成立,从“ Y ”执行 A 操作,不然从“ N ”执行后面的操作。 图 6‑7 ( c )是循环程序结构,所表达的语义是:条件成立,从“ Y ”执行 A 操作,然后返回到条件,再次判断进入循环;如果条件不成立,执行从“ N ” 执行后面的操作。 图 6‑7 程序流程基本结构 流程图的应用 在进行程序设计的时候,可以先不去考虑具体的指令,集中精力思考操作的相互关系,用流程图表达出来,然后再用具体的指令书写成汇编程序。实际上这种方法在较大的程序设计中是一种有效的手段。作为例子,将上面的两个 例 题的流程图画出(见 图 6‑8 )。 例题 【例 6‑1 】的详细流程图是将每一个指令的操作都画出了操作框( 图 6‑8 ( a )),实际上完全可以将一个完整的动作画成一个操作框,这样就可以得到简单一些的流程图(见 图 6‑8 ( b )),后者比起前者来,语义表达自然清楚,也比较简练。 图 6‑8 程序流程 例题 【例 6‑2 】的求 MN 乘积的流程图,就可以应用简单的画法给出,结果如 图 6‑8 ( c )所示。实际的流程图就常用自然的语言来描述。操作框有时可以代表一个简单的操作,也可以表示一个很复杂的操作,甚至代表一个程序。对于操作框,需要时可以再用流程图将复杂的操作过程画出来,程序设计的子程序调用问题,就使用这种方法在流程图中表示。操作框的层层深入,可以作到程序描述的由粗到细,有利于程序的结构化设计。
5. 原型 CPU 设计 这一部分将介绍 CPU 的整体设计,这种设计现在被称为微体系结构。自从有了高速缓存 cache 之后, CPU 的概念已经转化成“核”,即能够运行程序的单位。为了简单先设计一个原型 CPU ,存储器是特制的只读存储器。 5.1. 原型 CPU 的结构 5.1.1. EROM 将程序预先以某种工艺放入某种存储器,使用时只能读而不能写,这种存储器叫只读存储器( ROM )。 图 5‑1 是有 16 个存储单元的 8 位只读存储器。每个地址线 ad i 就是一个存储单元。数据线 d k 与地址线 ad i 之间用带开关的二极管连接,被选中单元开关接通,那一位数据就是 1 ,不然是 0 。这个 ROM 可以事先手动输入数据和程序,因而叫可输入只读存储器,简记为 EROM 。 图 5‑1 可输入的 ROM 以只读存储器 EROM 代替输入设备,以发光二极管组代替输出设备,并且只能作加、减法运算的计算机,应该是最简单的 CPU 了。这种计算机实际上是省略了输入输出设备,突出了计算机的核心部件。 5.1.2. 整体结构 能够做加减运算 CPU 的整体结构如 图 5‑2 所示。它是在加减法运算器的基础上改造而来的,比计算器要复杂一些,特别是增加了控制器,从而使这个机器的自动化程度比计算器有了本质的提升。 图 5‑2 加减运算 CPU 结构 这个计算机包括可输入只读存储器 EROM 、地址寄存器 MAR 、程序计数器 PC 、指令寄存器 IR 和控制器 CON ,时钟直接由控制器 CON 给出。这个计算机的内部总线 Bus 由 8 条导线组成,指令寄存器 IR 、输出寄存器 O 、数据寄存器 B 、 A 和加减运算器 ADD/SUB 都是 8 位的,它们都和内部总线相连,通过总线交换数据;地址寄存器 MAR 和程序计数器 PC 都是 4 位的,直接和总线的低 4 位相连。这样内部总线既可以传输 8 位的数据,也可以传输 4 位的地址信号。输出寄存器 O 的输出直接连接发光二极管组,通过发光二极管组显示输出寄存器 O 的内容。图中以 L 开头的短线,代表寄存器的写数据控制端,称为 L 门;以 E 开头的短线代表寄存器的输出控制三态门,叫做 E 门。 5.1.3. 逻辑组成 加减运算 CPU 的逻辑组成的五部分,分别是 (1) 运算器。它包括 ADD/SUB 、 A 、 B 。 (2) 存储器。它包括 MAR 和 EROM 。 (3) 控制器。它包括 PC 、 IR 、 CON 。 (4) 输入装置 EROM 的开关组。 (5) 输出寄存器 O 和发光二极管。 运算器和控制器过去一般统称为 CPU ,现在的 CPU 还包括 cache (静态存储器)。 5.1.4. 设备功能 这个原型 CPU 比加减法计算器增加了累加器、可输入只读存储器、程序计数器、指令寄存器和控制器。 累加器 寄存器 A 不但可以存放运算器运算前的数据,而且用来存放每次运算的结果,在多次连续的加法运算中,寄存器 A 起到了累加的作用,因而把 A 叫累加器。它有 L 门、 E 门控制数据的输入输出,能与总线直接进行数据交换。它的另一个输出端与 ADD/SUB 的输入端数据线直接相连,这个输送没有 E 门的控制。 寄存器 B 是与寄存器 A 配合使用的缓冲寄存器,它的输出端直接与 ADD/SUB 的另一个输入端相连,故可以把从总线接收的数据直接送到 ADD/SUB 的另一个输入端。寄存器 B 只是从总线上接收数据,而不需要将内容直接送到总线,故不用 E 门控制。 可输入只读存储器 可事先输入数据的输入只读存储器 EROM ,既充当存储器,也充当输入装置。 EROM 共有 16 个存储单元,前端有地址译码器,通过 4 位的存放存储单元地址的寄存器 MAR ,确定正在使用的存储单元,并且 EROM 的 E 门能控制存储单元的数据向总线输出。 地址寄存器 MAR 通过 L 门从内部总线 Bus 接收地址数据,并将地址数据直接送到 EROM 的地址译码器,从而选中需要的存储单元。 程序计数器 程序计数器 PC 的初始值是 0 ,它的加 1 功能,可以使它连续地指向每一个存储单元。假如若干个指令是从 0 号存储单元开始存放的,那么开始时将 PC 的值送到 MAR ,就可以选中第一条指令,在执行指令的过程中使 PC 加 1 ,那么在执行完一条指令之后,就又会将下一条指令执行,这样计算机就会不断地自动地运行下去。 指令寄存器 可控缓冲寄存器 IR 是专门放置指令的,因而被称为指令寄存器。在指令放到 IR 中的时候,有指令译码器翻译指令编码,这样就能够知道这时执行的是什么指令,以及数据放在哪里等。指令寄存器 IR 从总线接收指令数据,能够将指令数据的高 4 位和低 4 位分开。如果它的高 4 位放置指令编码,低 4 位放置数据的地址,那么高 4 位直接送到控制器的指令译码器,低 4 位可以再通过内部总线送到 MAR 或 PC 。 控制器 控制器 CON 是发出控制信号的地方,它有 12 条输出线,分别连接在各个设备的控制线上,它同时发出 Clr 和 Clk 控制信号,其中还包括电源开关等,其详细结构下面将专门讨论。 5.1.5. 计算机控制字 完整计算机的基本动作是由它的所有控制线的值来决定的,计算机所有控制线排列所成的字,在计算机状态变化中起着决定性的作用,也就是说计算机的一切动作发生都由这个排列字指挥。 定义 5‑1 除了 Clr 和 Clk 之外的全部控制线排列所成的一个字,叫 计算机控制字 。 这个加减运算 CPU 的计算机控制字是: C p E p L m E r L i E i L a E a S u E u L b L o 这个计算机控制字有 12 线,每一条线的取值不是 0 就是 1 ,所以每条线又是一个逻辑变量,这些变量的值是一个 12 位的二进制数,它的有序变化,就决定着这个计算机的全部运动。 例如, C p E p L m E r L i E i L a E a S u E u L b L o =100000000000 ,当 Clk 由 0 变到 1 的瞬间,计算机 PC 的值会加 1 ,而 C p E p L m E r L i E i L a E a S u E u L b L o =011000000000 ,当 Clk 由 0 变到 1 的瞬间,程序计数器的值会通过总线传输到地址寄存器,通过 MAR 直接输送到连接的地址译码器,选中只读存储器 EROM 中由 PC 指示的存储单元。 5.2. 计算机功能设计 5.2.1. 可实现功能分析 计算机能够干什么事情,实现怎样的功能,这和计算机的结构直接相关。 图 5‑2 的总线结构能够进行数据传送,所以可以让 EROM 存储的数据送到累加器 A ,以便从 A 分发到各处,比如将数据从 A 送到输出寄存器 O 显示输出。当然也可以选择让 EROM 存储的数据直接送到输出寄存器 O 显示输出,或者让 EROM 存储的数据直接送到寄存器 B 或寄存器 IR 等。 由于有加减法运算器,自然这个计算机具备加减法运算的功能。要实现 EROM 的数据能进行加法或减法运算,必须现将 EROM 的数据送到寄存器 A 和 B 中,这种能力这个计算机是完全具备的。 由于寄存器 O 、 B 、 MAR 都没有输出控制的 E 门,因而也就都没有向总线输出数据的功能,不能够将它们接收的数据再分发到总线上的其他设备。相反, PC 和 EROM 没有从总线上接收数据的 L 门控制线,所以它们没有从总线接收数据的功能。 指令寄存器 IR 有输入输出控制线,所以可以从总线接收数据,也可以将数据送到总线。它的高 4 位直接送到了控制器 CON ,这样放在其中的数据,就能够将高 4 位和低 4 位分开,并且通过总线可以将低 4 位数据送到 MAR 或 PC 。虽然 IR 输出的数据是 8 位的,但 MAR 或 PC 只通过连线接收 4 位,不至于出现混乱。 IR 的值可以传输到寄存器 A 、 B 、 O 。 地址寄存器 MAR 能够从总线接收 PC 、 A 、 IR 、 EROM 送到总线上的低 4 位数据,并将这 4 位数据做为地址信号,送到 EROM 的地址译码器,选中存储单元。 程序计数器 PC 可以通过控制线 C p 实现加 1 的功能,初始化控制线 Clr 会使它的初始值为 0 。 Clk 时钟线连接在每个设备的时标线上,可以控制整个系统按着时间要求工作。 5.2.2. 指令系统 设计 计算机结构能够提供的功能并不是我们都需要的,根据实际需要可以将一些功能组织到一起,形成对我们有用的工作模式。这就是计算机的指令设计问题。 指令执行过程 指令和数据都要存放在计算机的存储器中,执行指令的一般过程: (1) 将程序计数器的内容送到地址寄存器,选中指令存储单元; (2) 将存储器选中单元的内容送到指令寄存器进行译码和分析; (3) 将程序计数器加 1 ,准备取下一条指令; (4) 根据译出的指令线和节拍线的变化,完成该指令的模式动作。 这其中( 2 )的实现在这个原型 CPU 中是 IR 的高 4 位和低 4 位的可分性。如果将指令写成“指令编码 数据地址”的形式,那么就可以用 4 位的二进制编码表示指令,同时用 4 位的二进制数指出存储单元的地址。例如,“将某存储单元的内容送到累加器 A ”这个指令用二进制数 0000 来表示,那么具体的地址就可以写在这个编码的后面。这样将“将 5 号存储单元的内容送到累加器 A ”,就可以写成 0000 0101 。 用二进制数表示的指令编码,一般叫操作码,操作码后面写出的二进制数叫操作数。这种先写操作码后写操作数的形式就叫做指令格式。冯 . 诺依曼计算机中指令格式是实现程序执行的重要一环,正是由于指令两部分的合写和拆分,形成了计算机的各种基本动作,从而使指令功能的实现,能通过一连串变化的基本动作完成。 指令 设计 依据计算机的硬件构成(不包括控制器),来确定计算机能完成的基本任务,体现在计算机指令设计的过程当中。 定义 5‑2 一台计算机所能够识别的全部指令叫这台机器的 指令系统或指令集 。 一台计算机的指令系统设计,既和计算机的硬件构成有直接关系,也和设计者要求及计算机能完成那些基本任务有关。因而会出现即使是相同的计算机结构也会有不同的指令系统的现象。计算机的指令设计是很有学问的,一般地应将那些最基本的任务设计成指令,也就是说通过这些基本任务的指令组合,可以完成更加复杂的任务。 根据需要,加减运算 CPU 的指令系统设计,具体如 表 5‑1 所示。由于计算机能够完成的基本任务,会形成计算机的一种运行模式,成为一种功能,所以表中不标注基本任务,而是标注功能。 表 5‑1 的助记符一栏体现了指令的格式,其中 OUT 、 STP 没有操作数部分,可以认为是操作数隐含的一种特殊情况。 表 5‑1 指令系统设计 功 能 助记符 操作码 把某存储单元 R 的内容送到累加器 A LDA R 0001 把某存储单元 R 的内容与累加器 A 的内容相加结果送 A ADD R 0010 用累加器 A 的内容减去某存储单元 R 的内容结果送 A SUB R 0011 将累加器 A 的内容送到输出寄存器 O 输出 OUT 1000 停机 STP 1111 指令功能的设计中,首先考虑如何实现加法或减法的运算。因为数据是放在 EROM 中的,因此要先将一个数送到累加器 A ,然后再将另一个数送到寄存器 B 与 A 中的数相加,这样就设计了指令 LDA R 和 ADD R ,自然 SUB R 也是这样考虑出来的。运算的结果可以直接送到寄存器 O 输出,但如果是连续计算, A 要放中间结果,故而让累加器 A 的内容输出更加方便。 助记符表述的指令也是是由两部分组成的,前面是表示功能的指令码,指令码后面的部分是指令的辅助说明,辅助说明可以有多项,这里的辅助说明只有一项 R ,它表示存储器的地址。指令码和指令辅助说明组成的指令形式就是指令格式。指令格式的复杂度,取决于指令辅助说明的项目多少,一般地说,项目越多,指令的越复杂。用助记符表示的指令和计算机实际设计的指令是一一对应的,指令助记符在程序设计中称为汇编指令。 汇编指令组成的两部分,也分别叫操作码和操作数。计算机的指令可以带操作数,也可以不带操作数,但不能没用操作码。在进行指令处理时,总是要将操作码和操作数分开,由操作码来确定指令的一般功能,由操作数来指出具体的实施内容。 指令 全程分析 将多条指令从 EROM 的 0 号单元顺序存放,用程序计数器 PC 来指示将要执行的那条指令,并在执行指令的过程中让 PC 加 1 ,这样就能重复地通过 PC 的指示执行全部的指令,这一过程是计算机自动执行程序的要点。根据本计算机的结构的特点,现在来分析每条指令的执行过程。指令的执行的整个过程叫指令全程。 LDA 的指令全程 LDA 指令的执行过程如下: ( 1 )将程序计数器 PC 的值送到地址寄存器 MAR ; ( 2 )将 EROM 输出的内容送到指令寄存器 IR ; ( 3 ) PC 加 1 ; ( 4 ) IR 的低 4 位送到 MAR ; ( 5 ) EROM 输出的内容送到累加器 A 。 ADD 的指令全程 ( 1 )将程序计数器 PC 的值送到地址寄存器 MAR ; ( 2 )将 EROM 输出的内容送到指令寄存器 IR ; ( 3 ) PC 加 1 ; ( 4 ) IR 的低 4 位送到 MAR ; ( 5 ) EROM 输出的内容送到数据寄存器 B ; ( 6 ) A + B 的结果送到累加器 A 。 SUB 的指令全程 ( 1 )将程序计数器 PC 的值送到地址寄存器 MAR ; ( 2 )将 EROM 输出的内容送到指令寄存器 IR ; ( 3 ) PC 加 1 ; ( 4 ) IR 的低 4 位送到 MAR ; ( 5 ) EROM 输出的内容送到数据寄存器 B ; ( 6 ) A-B 的结果送到累加器 A 。 OUT 的指令全程 ( 1 )将程序计数器 PC 的值送到地址寄存器 MAR ; ( 2 )将 EROM 输出的内容送到指令寄存器 IR ; ( 3 ) PC 加 1 ; ( 4 ) A 的内容送到输出寄存器 O 输出。 上面各指令的指令全程的每一步都对应着一个计算机的基本动作,由此可见计算机的基本动作是计算机能够完成各种任务的基础。 从 LDA 、 ADD 、 SUB 的指令全程步骤( 4 )可以看到,要取出在存储器中的数据,都要将指令寄存器 IR 中的指令操作数回送到地址寄存器 MAR ,这是访问存储器的通行作法。将指令操作码和操作数进行拆分,是计算机指令分析不可缺少的一步。 微指令驱动 总线结构的计算机基本状态的变化,是由计算机控制字的值来确定的。这台计算机的控制字是 C p E p L m E r L i E i L a E a S u E u L b L o ,共 12 位,指令全程的每一步都可以用一个控制字的值来指挥,因此把计算机控制字的一个值称为一条微指令。 微指令的集合称为微指令程序。例如 LDA 的指令全程用微指令写出是: 011000000000 000110000000 100000000000 001001000000 000100100000 指令的微指令程序一般称为例行程序。 指令例行程序中的微指令必须严格地按着一定的顺序出现,每次微指令出现就会使计算机完成一个基本动作,这就是微指令的执行过程。由于每一个指令所包含的微指令是固定的,指令的执行就会重复执行例行程序的微指令,加上微指令执行的时间往往是固定的,所以顺次执行的微指令时间被称为机器节拍。 显然例行程序的微指令是节拍和指令的函数,也就是说,指令一定,节拍一定,那么微指令也就确定了。再进一步分析,微指令是计算机控制字的一个值,微指令的每一位数都是对应控制线的一个值,因此控制线的值也是由节拍和指令来确定的。如果将每条控制线理解成逻辑变量,那么它们就都是指令和节拍的函数。 将这台加减运算 CPU 的每条指令的例行程序都罗列出来进行分析,可以明确地反映这种函数关系。为了方便分析,把全部指令的节拍凑成一样的 6 拍,多余的节拍用空操作微指令“ 000000000000 ”填充, 表 5‑2 所示的就是这种情况。 由 表 5‑2 可以看出指令的执行是通过计算机控制字的变化来实现的,而计算机控制字的变化会随着节拍和指令的不同而不同,计算机控制字的每一个逻辑变量都是机器节拍变量和指令变量的函数。 无论是从指令全程的分析还是 表 5‑2 都可以看到,每个指令的前 3 拍都是一样的,这 3 拍的计算机控制字只随节拍变化,与指令无关。这 3 拍仅是将指令从 EROM 中取出来,放到指令寄存器 IR 中, PC 加 1 ,所以被认定只是一个取出指令的过程,叫指令的取指周期。每个指令的取指周期以外的动作过程叫指令的执行周期。取指周期和执行周期合起来的过程就是指令周期。计算机之所以能够自动地执行指令,从而完成任务,和指令的取指周期只在节拍的驱动下进行动作有关。 加减运算 CPU 的指令取指周期占 3 个节拍,而指令执行周期最多也是 3 个节拍,所以指令周期是 6 个节拍。 表 5‑2 指令和计算机控制字变化表 指令助记符 机器动作 节拍 C p E p L m E r L i E i L a E a S u E u L b L o LDA R PC → MAR 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 2 0 0 0 1 1 0 0 0 0 0 0 0 PC+1 3 1 0 0 0 0 0 0 0 0 0 0 0 IR → MAR 4 0 0 1 0 0 1 0 0 0 0 0 0 EROM → A 5 0 0 0 1 0 0 1 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 ADD R PC → MAR 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 2 0 0 0 1 1 0 0 0 0 0 0 0 PC+1 3 1 0 0 0 0 0 0 0 0 0 0 0 IR → MAR 4 0 0 1 0 0 1 0 0 0 0 0 0 EROM → B 5 0 0 0 1 0 0 0 0 0 0 1 0 A+B → A 6 0 0 0 0 0 0 1 0 0 1 0 0 SUB R PC → MAR 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 2 0 0 0 1 1 0 0 0 0 0 0 0 PC+1 3 1 0 0 0 0 0 0 0 0 0 0 0 IR → MAR 4 0 0 1 0 0 1 0 0 0 0 0 0 EROM → B 5 0 0 0 1 0 0 0 0 0 0 1 0 A - B → A 6 0 0 0 0 0 0 1 0 1 1 0 0 OUT PC → MAR 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 2 0 0 0 1 1 0 0 0 0 0 0 0 PC+1 3 1 0 0 0 0 0 0 0 0 0 0 0 A → O 4 0 0 0 0 0 0 0 1 0 0 0 1 5 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 STP PC → MAR 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 2 0 0 0 1 1 0 0 0 0 0 0 0 STOP 3 0 0 0 0 0 0 0 0 0 0 0 0 5.3. 控制矩阵设计 计算机的动作都是由微指令来指挥的,而微指令的产生又是由机器节拍和指令来决定的,因此计算机的动作和它们之间的逻辑关系密切相关。由机器节拍和指令变动产生微指令的逻辑电路是计算机控制的核心,这个核心逻辑电路称为计算机的控制矩阵。 5.3.1. 控制矩阵中的 函数 用线表示指令 分析 表 5‑2 可以看出自变量就应该有 11 个,那就是节拍 1 、 2 、 3 、 4 、 5 、 6 ,指令 LDA 、 ADD 、 SUB 、 OUT 、 STP 。为了方便书写,将节拍和指令都设置成一位的代码,各自的代码就如 表 5‑3 所示那样。 STP 指令的作用是停止计算机运行,它的作用不通过计算机控制字来完成,因此设计机控制矩阵不用设置 STP 的代码,这样自变量考虑 10 个就可以了。因变量就是每个设备的控制线,这里一共有 12 条。 表 5‑3 节拍和指令代码 节拍名称 代码 变量名称 代码 第六拍 A LDA G 第五拍 B ADD H 第四拍 C SUB I 第三拍 D OUT J 第二拍 E STP 第一拍 F 前面的分析多次说明要将指令的操作码和操作数放到指令寄存器 IR 中,其目的有两个。其一,将指令码转化成一条能够标志该指令执行的线;其二,将指令的操作码和操作数分离,以便进行相应的处理。 指令操作码可以通过译码器转化成各自的标志线 。 图5‑3 是将指令寄存器的高4位引出线通过译码器译出指令线的逻辑电路 。实际当中,只要哪一个指令的操作码进入指令寄存器 IR ,立即在 的输出端就会有相应的指令线为1,表明执行的是这一条指令。 图 5‑3 指令译码器 节拍器 例行程序的 6 个节拍可以用一个 6 位的环行计数器的输出端表示。 图 5‑4 中当 Clr=1 时输出端 F=1 ,进入第一个节拍,以后每一次 Clk=1 都会使为 1 的输出端向左移动一位,从而顺次表示 2 、 3 、 4 、 5 、 6 拍。 图 5‑4 节拍器 控制矩阵真值表 将这些自变量和因变量的值变化过程列成真值表,就得到 表 5‑4 。根据逻辑变量运算式 A+A=A 知道,在真值表中相同的部分作用是相同的,所以表中每个指令的指周期的 3 个节拍就简写成一个。由于前 3 个节拍因变量的变化是与指令无关的,因而表中这部分指令变量的值用空白表示。表中 1~3 行是各指令的取指周期, 4~6 行是指令 LDA 的执行周期, 7~9 行是指令 ADD 的执行周期, 10~11 行是指令 SUB 的执行周期, 13~15 行是指令 OUT 的执行周期。 表 5‑4 控制矩阵真值表 机器动作 A B C D E F G H I J C p E p L m E r L i E i L a E a S u E u L b L o PC → MAR 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 EROM → IR 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 PC+1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 IR → MAR 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 EROM → A 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 无动作 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 IR → MAR 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 EROM → B 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 A+B → A 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 IR → MAR 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 EROM → B 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 A - B → A 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 0 A → O 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 无动作 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 无动作 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 逻辑函数 根据 表 5‑4 各行之间是或的关系,同行自变量的值是与的关系,应用因变量的逻辑函数求法,得 C p =A'B'C' D E'F' E p =A'B'C'D'E' F L m =A'B'C'D'E' F +A'B' C D'E'F'( G H'I'J'+G' H I'J'+G'H' I J') E r =A'B'C'D' E F'+A' B C'D'E'F'( G H'I'J'+G' H I'J'+G'H' I J' ) L i =A'B'C'D' E F' E i =A'B' C D'E'F' ( G H'I'J'+G' H I'J'+G'H' I J') L a =A' B C'D'E'F' G H'I'J'+ A B'C'D'E'F'(G' H I'J'+G'H' I J') E a =A'D' C E'F'G'H'I' J S u = A B'C'D'E'F'G'H' I J' E u = A B'C'D'E'F'(G' H I'J'+G'H' I J') L b =A' B C'D'E'F'(G' H I'J'+G'H' I J') L o =A'B' C D'E'F' G'H'I' J 在环形计数器中,因为 E=1 必有 A=B=C=D=F=0 从而 A'B'C'D'EF'=1 而当 E=0 时,不论、 A 、 B 、 C 、 D 、 F 为何值都有 A'B'C'D'EF'=0 于是有 A'B'C'D'EF' =E 同理 A'B'C'D'E'F=F A'B'C'DE'F'=D A'B'CD'E'F'=C A'BC'D'E'F'=B AB'C'D'E'F'=A 对于一台计算机来说,各指令之间也是两两互相排斥的,故也有 GH'I'J' =G G'HI'J' =H G'H'IJ' =I G'H'I'J =J 这样,上面的逻辑表达式可以化成 C p =D E p =F L m =F+C(G+H+I) E r =E+B(G+H+I) L i =E E i =C(G+H+ I) L a =BG+A(H+ I) E a =CJ S u =AI E u =A(H+I) L b =B(H+I) L o =CJ 5.3.2. 控制矩阵电路 根据上面计算机控制字的 12 个因变量的函数,很容易画出这台加减运算 CPU 的控制矩阵电路图。 图 5‑5 的上面 6 条线是节拍线,接下来的 4 条是指令线,下面的输出是计算机控制字的 12 条线。这种能够发出计算机控制字的电路,设计起来总是纵横交错的形式,看起来很像矩阵,因而称为计算机的控制矩阵。 加减运算 CPU 的控制矩阵相对是比较简单的,复杂计算机的纵横导线会成百上千,设计图会非常庞大。实际设计中可以将控制矩阵的设计分块进行,然后根据块间的逻辑关系进行增添。在不同的块之间控制线会出现重复,根据重复的控制线之间是逻辑或的关系,再大的控制矩阵也容易设计出来。 图 5‑5 控制矩阵的电路 5.4. 控制器 和整机工作过程 5.4.1. 控制器 这台加减运算 CPU 的控制器在 6 个节拍中有序地发出微指令,从而完成每条指令的执行过程。整个控制器的电路如 图 5‑6 所示,这里指令寄存器 IR 的高 4 位直接连接在指令译码器的输入端,而指令译码器的输出端就是 4 个指令的指令线。指令线和 6 位环行计数器的输出端,直接成为了控制矩阵的输入端。 图 5‑6 控制器电路 5.4.2. 整机工作过程 这台计算机的整机工作过程如下: 当使用的人合上电源开关之后,由 图 5‑6 可以看出瞬间有一个高电位使得触发器置位,于是接在这个触发器 Q 端的时钟脉冲振荡器马上开始工作,不断地发出高频的时钟脉冲。在启动开关合上同时, Clr 端也瞬间为 1 ,于是相应的设备被初始化,在时钟震荡之前形成程序计数器 PC=0000 ,环形计数器的值为 000001 等。 ( 1 ) Clr 是瞬间作用的,故当有效时钟脉冲到来的时候,机器的各种设备已经进入了正常工作状态。由于 F=1 ,于是从控制矩阵发出的计算机控制字是 011000000000 ,即 E p =1 , L m =1 。这样,当第 1 个时钟脉冲到来时, PC 中的值 0000 送到了 MAR ,于是就选中了 0000 号单元。 ( 2 ) 与此同时, Clk 到来使环行计数器的值变成了 000010 ,即 E=1 ,于是第 2 个时钟脉冲到来之前, E r =1 , L i =1 。当第 2 个时钟脉冲到来之时, 0000 号单元的内容被送到了指令寄存器 IR ,这时 IR 将其高 4 位送到 CON 的指令译码器。 ( 3 ) 与此同时,环形计数器的值变成了 000100 ,即 D=1 ,于是第 3 个时钟到来之前只有 C p =1 。当第三个时钟脉冲到来之时 PC 加 1 ,第 4 个节拍变量 C=1 。 以上( 1 ) ~ ( 3 )是取指周期的工作,继后到来的时钟脉冲将要完成对取出的 0000 号单元的指令的执行工作,( 4 ) ~ ( 6 )进入执行周期。 ( 4 ) 假如 0 号存储单元存储的指令是: LDA 1010 ,那么从第 2 个节拍之后,通过指令译码器的工作, LDA 的指令线 G 就一直为 1 。它和节拍 C 合作使 E i =1 , L m =1 ,当第 4 个时钟脉冲到来时,使第 5 个节拍线 B=1 ,从而使 E r =1 , L a =1 。 ( 5 )第 5 个时钟脉冲到来之前 E r =1 , L a =1 ,当 Clk 由 0 变到 1 的瞬间,就将 1010 存储单元的内容送到累加器 A 了。与此同时节拍线 A=1 。 ( 6 ) 在节拍变量 A=1 之后的第 6 个 Clk=1 到来之后,又会有节拍线 F=1 。 ( 1 ) ~ ( 6 )的循环重复,可以不断地执行在存储器中顺序存放的指令。 如果指令寄存器 IR 中得到的指令代码是 1111 ,那么指令译码器译出的高电位线直接送到启动停止触发器的 R 端,至使 Q=0 , 于是就停止了时钟脉冲振荡器的震荡,也就使这台计算机停止了工作。 5.4.3. 时序 一台计算机有许多部件组成,要使这些部件有条不紊地进行工作,就必须要它们按照一定的时间顺序动作,这就是计算机时序问题。计算机中信息的流动有先有后,如果传输的过程中颠倒了顺序,必然会出现错误的结果。因此计算机的设计分析中,将时序都放在一个很重要的位置考虑,尤其是在多条信息通路进行数据传送时,更要注意哪一路数据先到达,是否会错序。如果发生了时序的错误,那么或者设法加快较慢的一路传输速度,或者降低较快的一路传输速度,以便调整到正确的时间顺序。 主频与节拍 计算机的时间顺序是由计算机的频率时钟来确定的。控制器中石英振荡器产生的震荡频率一般叫计算机的主频。计算机的主频表明计算机的 CPU 运行速度,是计算机十分重要的参数。主频的一个振荡周期决定计算机的一个基本动作,因而称之为一个机器节拍。计算机的时序是用节拍来量度的。 为了研究方便,在总线结构的计算机系统中,又提出总线周期、指令周期、取指周期、执行周期等概念。 所谓的总线周期是指总线传输一个单位数据所需要的节拍数。设计的加减运算 CPU ,传送一个单位数据只要一个节拍,而有的计算机可能需要两个以上的节拍。 取指周期是从存储器中取出指令所需要的节拍数。加减运算 CPU 的取指周期是 3 个节拍。执行周期是执行取出的指令所需要的节拍数。加减运算 CPU 执行周期也是 3 个节拍。取指周期和执行周期组成了计算机的指令周期。加减运算 CPU 的指令周期是 6 个节拍。 时序图 为了研究时序,人们常用图来表示,这种图叫时序图(见 图 5‑7 )。图中从上到下分别代表主频,取指周期,执行周期和指令周期。从图上可以看到取指周期占 3 个节拍,执行周期占 3 个节拍并且是在取指周期之后。指令周期占 6 个节拍。 一般的时序图都要反映出主要部件间在时间上的相互协作关系,因而一个计算机的时序图要比 图 5‑7 复 杂得多,可以从时序图上清楚地知道各个部件工作的先后顺序,这在计算机仿真设计中有十分重要的作用。有兴趣的读者可以参考相关资料,在此不详细描述。 图 5 ‑ 7 时序 5.5. 顺序程序设计 一台计算机的控制矩阵确定了,也就相当于确定了这台计算机的指令集。根据计算机的指令集,就可以进行程序设计。下面就以例子来说明利用这台加减运算 CPU 如何来进行程序设计。 5.5.1. 汇编源程序 利用汇编指令进行程序设计,就叫做汇编程序设计。由于汇编指令是与具体的计算机直接相关的,因此实际使用的计算机汇编程序设计也比较复杂,当然这里给出的汇编程序设计就简单多了。为了方便,把数用方括号括起表示这个数所在的存储单元地址。 【例 5‑1 】 用汇编程序完成 3 + 2 + 1 - 4 的计算。 依据加减运算 CPU 的指令系统,可以设计如下的程序: LDA ADD ADD SUB OUT STP 这个程序解释是很容易的。第 1 条指令是说将数 3 装入累加器 A ;第 2 条指令是把数 3 和 2 相加结果 5 放在 A 里面;第 3 条指令是说将 1 与 A 的内容 5 相加,结果 6 放在 A 里面;第 4 条指令是说将 A 的内容 6 减去 4 ,并把结果 2 放在 A 中;第 5 条指令是说将 A 的内容 2 输出;第六条指令是说停止机器运行。 上面的程序可以说仅仅是逻辑上的设计,实际上这台计算机怎样执行程序还不清楚。怎样才能让计算机完成这项任务?这涉及到指令和数据在存储器中怎样存放的问题。 5.5.2. 存储器分配 根据指令程序的特点,可以把存储器分为两个区域,一个是存放指令的区域,叫代码区,另 一个存放要操作的数据的地方,叫数据区(见 图 5‑8 ) 。根据这台计算机的结构特点,代码 区一定要放在前面,从 0000 号存储单元开始。因为这台计算机一开机就去取 0000 号单元的数据,所以程序一定要从 0000 号单元开始存放。 由指令的格式知道,操作数是数据的地址,所以可以将数据放在代码区后面的任何位置,只要不和代码区重叠放置就可以。此题数据的起始地址是 1011 (2) ,顺序地存放了 3 、 2 、 1 和 4 ,当然放在存储器中的都要是二进制数。 图 5‑8 存储器分配 5.5.3. 编译 因为计算机只能识别二进制数,所以放入计算机存储器的指令和数据必须都是二进制数。用二进制数表示的计算机指令才能够被计算机识别,这种指令又叫机器指令。将汇编源程序翻译成可以被机器识别的二进制机器指令程序和数据的过程叫编译。把 【例 5‑1 】中的汇编源程序变成二进制数放在存储器中,得到 图 5‑8 所示 的存储形式,可以看到存储器中除了二进制数之外,没有别的东西( 图 5‑8 最右边的二进制数是地址编号)。 在将汇编指令翻译成机器指令的过程中,必须根据数据在存储器中的位置,确定指令的操作数,这要从前到后至少“扫描”两次。第一次,从前到后将操作码和数据翻译好,暂不确定操作数,并将这样的指令和数据在存储器中放好,确定出数据的地址。第二次,从前到后才能将每个指令的操作数确定。可见数据位置的确定,要求对数据的存放位置进行编排,所以整个翻译的过程是“边编排,边翻译”,因而将这一过程叫“编译”。 5.5.4. 程序执行 由于这台加减运算 CPU 是手动输入的,因此在拨动开关时必须位置准确。程序和数据都输入存储器的相应单元后,就可以让计算机来运行这个程序了。 将 【例 5‑1 】的具体的执行过程列成表,就是 表 5‑5 所示的情形。 表 5‑5 程序执行情况一览 节拍 指令 指令周期 取指周期 执行周期 F E D C B A 00011011 LDA PC=0000 PC=0001 L m , E p L i , E r C p L m , E i L a , E r PC → MAR ROM → IR PC+1 IR → MAR ROM → A 00101100 ADD PC=0001 PC=0010 L m , E p L i , E r C p L m , E i L b , E r L a , E u PC → MAR ROM → IR PC+1 IR → MAR ROM → B A+B → A 00101101 ADD PC=0010 PC=0011 L m , E p L i , E r C p L m , E i L b , E r L a , E u PC → MAR ROM → IR PC+1 IR → MAR ROM → B A+B → A 00111110 SUB PC=0011 PC=0100 L m , E p L i , E r C p L m , E i L b , E r S u , L a , E u PC → MAR ROM → IR PC+1 IR → MAR ROM → B A-B → A 1000 OUT PC=0100 PC=0101 L m , E p L i , E r C p E a , L o PC → MAR ROM → IR PC+1 A → O 1111 STP PC=0101 L m , E p L i , E r PC → MAR ROM → IR
辑电路及画法 1.4. 逻辑电路 实现计算机最关键的一步,是将信息的表示和处理都能够用物理设备完成。电脑要替代人脑进行工作,必须能够用物理器件完成布尔代数的基本运算。 由于布尔代数中集合的元素只有 0 和 1 ,这样就很容易用电器元件的两种状态来表示,进而制成逻辑电路。利用许多电子元件都可以作出布尔代数中或、与、非运算的器件,但是设计计算机所使用的器件必须满足易检测,易控制修改的要求才行。了解半导体知识的人都知道,半导体晶体管就可以达到这些要求,因此在此仅以理想的半导体晶体管电路来说明或、与、非逻辑电路的组成及工作原理。 1.4.1. 二极管和三极管 不论是否学习过晶体管电路知识,下面叙述的内容要认真记住,因为这些内容是学习逻辑电路最基本的内容,掌握好这些内容是理解计算机电路的重要条件。 简单电路知识 在电路的研究中一般使用电路图。 图 1‑6 是一个直流电路图,图中“ a ”表示导线,长短线段组“ GB ”表示直流电源, GB 的长线一端是正极,矩形(或弹簧线)“ R ”表示电阻,斜线“ S ”表示开关。直流电源的长线段一端是高电位,另一端是低电位,当开关 S 接通时,就有电流从上到下流过电阻 R 。中学的电学知识指出“电阻的电流流入端是高电位,流出端是低电位”,“连接在一起的电路如果没有电流通过,那么各点的电位相同”,“只用导线连接的电路各点任何情况下电位都相同”。 二极管电路 图 1‑7 是晶体二极管的电路符号,它的特性是 a 端高电位、 b 端低电位时, a 到 b 有电流通过,这种情况叫导通。如果 a 端是低电位、 b 端高电位,那么 ab 之间就没有电流,这种情况叫截止。二极管是组成逻辑电路的重要元件。 三极管电路 三极管的简单符号如 图 1‑8 所示, b 端叫基极, e 端叫发射极, c 端叫集电极。使用中 c 端和 e 端要加固定的电位。三极管的特性是:当 b 为高电位时, ec 之间导通,而 b 为低电位时, ec 之间截止,即 ec 之间几乎是断开状态。 关于二极管和三极管的详细特性及工作原理,在逻辑电路问题中,不必深究,只要掌握上面提到的这些属性,就可以理解逻辑电路的相关问题。如果想要了解更多的细节,可以查阅相关电路知识的书籍和资料。 1.4.2. 基本逻辑门电路 利用二极管和三极管可以组成能够实现逻辑运算的基本电路,这些基本逻辑电路分别称为或门电路、与门电路和非门电路。 或门电路 图 1‑9 ( a )所示的是或门电路,它是用两个二极管并联再和电阻串联组成的电路,粗短线表示接地,接地表示低电位。如果将 a 、 b 、 c 高电位用 1 记,低电位用 0 记,那么由二极管的单向导电性可知,当 a 或 b 有一个是高电位时(即 a=1 或 b=1 时),至少就有一个二极管导通,于是 R 就有从上往下的电流通过, R 的上端 c 相对于另一端是高电位,即有 c=1 。 只有当 a 和 b 都是低电位时( a=0 且 b=0 ),两个二极管都不导通, R 上就没有电流通过, R 的上端和 R 的下端电势相同,都为低电位,即 c=0 。容易验证或门电路的状态和或运算的真值表的值是一样的,因而或门电路可以表达逻辑的或运算。 或门电路今后用 图 1‑9 中 (b) 所示的简单符号来记, a , b 叫输入端, c 叫输出端。 图 1‑9 ( b )的左图是我国规定的符号,右图是设计软件中使用的符号。 与门电路 同或门电路一样,可以用 2 个三极管组成 图 1‑10 (a) 所示的与门电路。这个电路的工作原理是:当两个三极管的基极 a , b 同时加上高电位时,两个三极管都导通,于是电阻 R 才有由上向下的电流,这样 c 端就是高电位(即 c=1 ),不然,或者 a=0 ,或者 a=b=0 ,或者 b=0 ,此任何一种情况都会使两个三极管至少有一个处在截止状态,这样电路就处于断开状态,电阻 R 没有电流通过。由于 c 端通过电阻 R 和“地”相连,地是低电位,故而 c 端是低电位。 从数值上看,与门电路的 a , b 任何一端为 0 都可以使 c 端的值为 0 。例如令 a=0 ,则 c=0 ,这样 a 就起一个控制端的作用,它能够控制 c 端使之为 0 。同样, b 端也有相同的作用。 容易验证与门电路的状态和与运算的真值表的值是一样的,因而与门电路可以表达逻辑的与运算。 与门电路的符号如 图 1‑10 (b) 所示,同样 a 、 b 是输入端, c 是输出端。 图 1‑10 (b) 的左图是我国规定的符号,右图是设计软件中使用的符号。 非门电路 非门电路也用三极管组成。 图 1‑11 (a) 中的非门电路的 R 是负载电阻。当 a 端高电位即 a=1 时,由于三极管导通,相当于 c 与地直接相连,于是 c 点的电位和地一样,就是 0 。而当 a=0 时,由于三极管处在截止状态, c 通过 R 与下端高电位一样,则有 c=1 。 非门电路的符号如 图 1‑11 中的 (b) ( c )( d )所示。在电路图的描述中,本书推荐使用图中( c )的画法,因为它描述简单利落,容易和其他电路组合在一起,能直观地表达复杂的逻辑关系。图中( d )的画法在软件中使用。 1.4.3. 组合电路 有了基本的或、与、非三种逻辑门电路,就可以组织一些较复杂的逻辑电路了。设计逻辑电路时,如果先知道逻辑表达式,那么要确定好自变量与因变量,弄清楚逻辑运算的先后次序,这样就会很容易根据基本的逻辑电路,做出逻辑表达式的电路图。 导线连通的表示 图 1‑12 导线连接与交叉 在电路的绘制中经常会碰到导线交叉,交叉的导线有时是连通的,有时又不是连通的。为了区分交叉的两条导线是否连接在一起,电路图中这样规定:当有两条导线连通时,可以错开画,也可以在交点涂一黑点( 图 1‑12 (a) ),不涂黑点,就表示两条导线没有连通( 图 1‑12 (b) )。如果电路中导线出现丁字连接,则规定一律是连接在一起的,为了美观,画图中经常将十字连接的导线改成 2 个丁字连接的形式。 简单组合电路 简单常用的组合逻辑电路有或非门、与非门、异或非门等。 或非门 根据逻辑等式 C=(A+B) ’ 画出的电路如 图 1‑13 所示,( a )是我国规定画法,( b )是软件中的画法,四周围的虚线不起作用,主要是为了辅助识别。这个电路叫或非门。或非门电路是由一个或门电路和一个非门电路连接在一起组成的。画逻辑电路图,要根据逻辑表达式的运算顺序,从输入端画起,到输出端为止。或非门要先画或门电路,然后再画非门电路。 图 1‑13 或非门符号 与非门 根据逻辑等式 C=(AB) ’ 画出的电路如 图 1‑14 所示,( a )是我国的符号,( b )是软件中使用的符号,这个电路叫与非门。 图 1‑14 与非门符号 异或门 根据逻辑表达式 C=A B=A ’ B+AB ’ ,可以画出异或门电路。 图 1‑15 ( a )是异或门的组成电路, (b) 是它的电路符号(左端是我国规定的符号,右端是软件使用的符号)。 图 1‑15 异或门电路及符号 异或非门 图 1‑16 异或非门的符号 用符号来表达电路可以达到简单清晰的效果。 图 1‑16 是用异或门符号和非门符号组合到一起表达的异或非门运算 C=(A B) ’ 的电路,( a )是我国的符号,( b )是软件中使用的符号。 通过简单组合电路的画法,可以初步了解逻辑电路的组合形式,依据这种组合方式可以画出更复杂的逻辑电路。 1.4.4. 逻辑电路 的画法 逻辑电路是依据表达式画出的,画逻辑电路时要依据逻辑运算的先后顺序,先画自变量的部分,每一个自变量用一条导线表示,然后根据逻辑关系用逻辑门连接,最后得到因变量的输出线。下面举两个根据逻辑表达式画出电路图的例子。 【例 1‑17 】 逻辑表达式 Y=AB+A ’ BC ’ +AC ,画出电路图。 用导线 A 、 B 、 C 表示自变量 A 、 B 、 C ,按着逻辑函数右面的运算顺序,先用与门连接,然后再用或门连接,最后得到输出线 Y ,它就是逻辑变量 Y 。最后的结果如 图 1‑17 所示。 图 1‑17 组合逻辑电路 当表达式有异或运算时,可以先根据公式 A ’ B+AB ’ =A B 将表达式化简整理后再画电路图。 【 例 1‑18 】 Y= ( A ’ B+AB ’ ) C+A ’ C+AC ’ 根据这个表达式画出电路图。 根据这个表达式得到 图 1‑17 的逻辑电路。 图 1‑18 用异或画出的逻辑电路 此 例 的化简并不是一定是最简单的,假如手中有许多的异或门,这种化简是合适的。逻辑电路设计中常要根据手中的门电路元件来确定化简方向。
开头的话 为把更多的青少年带入计算机核心设计的殿堂,消除对神秘机器智能系统的崇拜。有三十多年计算机教学经验,现在还从事 CPU 等计算机核心设计的姜老师,愿带领具有高中文化水平的计算机爱好者,一起来做一次 CPU逻辑 设计。 借助于科学网的平台,姜老师会以博文的方式,连续给出 CPU 的基本设计,如果你有兴趣,那么就一起来吧。 2014-7-30
对外经济贸易大学 姜咏江 CPU控制逻辑一般都可以用真值表分析,用有限状态机FSM进行描述。就逻辑电路而言,各种逻辑描述最终都得转化成逻辑与门、或门、非门的组合形式。给大家介绍一个本人设计的CISC指令系统的控制逻辑电路自动生成器,可以免去FSM描述的麻烦,又不会出错,大家不妨试试。按照这个思路也可以设计RISC指令系统的控制逻辑电路生成器,因一直较忙,尚未动手。 1 指令分析真值表 无论何种CPU设计都离不开图1所示的指令分析真值表。 图 1 指令分析真值表 指令分析真值表分为左端的自变量部分和右边的因变量部分。自变量一般包括机器指令线、节拍线和标志线。因变量部分包括计算机的所有控制线。本设计中用复位线res作为自变量部分和因变量分界,使用中一定要确定好分界。表格中前四项的位置不能变,特别是助记符和节拍不能和基本动作后面的自变量混序。除了编号助记符节拍基本动作和res之外,变量的名称可以自己随便更改。节拍必须用向量的方式p p; input LDA,ADD,SUB,OUT,JMP,JZ,JN,CALL,IN,STR,SDA,PUSH,POP,RET,INC,DEC,ZERO,INP,STRP,JEND,LNOT,LAND,LOR,STPK,JK,MULT,DIVI,DATX,XTDA,STP; input EMPTY,ENDF,ZF,NF; output RES,PCE,PCL,PCINC,IMARL,DMARL,IRAML,IWRIT,IRAME,DRAML,DWRIT,DRAME,DAE,DAL,ZEO,COML,AL,BL,A_SE,SU,SPE,SPINC,SPDEC,PTRE,PTRL,PTRINC,PTRDEC,OL,INE,IRE,IRL,XL,XE,NOTE,ANDE,ORE,CHENGE,CHUE,GAOWEIE,STOP; assign RES=LDA p |ADD p |JMP p |JZ p |JN p |CALL p |STR p |SDA p |PUSH p |POP p |RET p |INC p |DEC p |ZERO p |INP p |STRP p |JEND p |LNOT p |LAND p |DATX p |XTDA p ; assign PCE=p |LDA p |ADD p |SUB p |OUT p |JMP p |JZ p |JN p |CALL p |CALL p |IN p |STR p |SDA p |JEND p |LAND p |LOR p |JK p |MULT p |DIVI p ; assign PCL=JMP p |JZ p ZF|JN p NF|CALL p |RET p |JEND p ENDF|JK p EMPTY; assign PCINC=p |LDA p |ADD p |SUB p |OUT p |JZ p |JN p |CALL p |IN p |STR p |SDA p |JEND p |LAND p |LOR p |JK p |MULT p |DIVI p ; assign IMARL=p |LDA p |ADD p |SUB p |OUT p |JMP p |JZ p |JN p |CALL p |IN p |STR p |SDA p |INP p |JEND p |LAND p |LOR p |JK p |MULT p |DIVI p ; assign DMARL=LDA p |ADD p |SUB p |OUT p |CALL p |IN p |STR p |PUSH p |POP p |RET p |LAND p |LOR p |MULT p |DIVI p ; assign IRAML=INP p |MULT p ; assign IRAME=p |LDA p |ADD p |SUB p |OUT p |JMP p |JZ p ZF|JN p NF|CALL p |IN p |STR p |SDA p |JEND p ENDF|LAND p |LOR p |JK p EMPTY|MULT p |DIVI p ; assign DRAML=CALL p |IN p |STR p |PUSH p ; assign DWRIT=CALL p |IN p |STR p |PUSH p ; assign DRAME=LDA p |ADD p |SUB p |OUT p |POP p |RET p |LAND p |LOR p |MULT p |DIVI p ; assign DAE=ADD p |SUB p |STR p |PUSH p |STRP p |LNOT p |LAND p |LOR p |MULT p |DIVI p |DATX p ; assign DAL=LDA p |ADD p |SUB p |SDA p |POP p |LAND p |LOR p |MULT p |DIVI p |XTDA p ; assign ZEO=ZERO p ; assign COML=p ; assign AL=ADD p |SUB p |LNOT p |LAND p |LOR p |MULT p |DIVI p ; assign BL=ADD p |SUB p |LAND p |LOR p |MULT p |DIVI p ; assign A_SE=ADD p |SUB p ; assign SU=SUB p ; assign SPE=CALL p |PUSH p |POP p |RET p ; assign SPINC=POP p |RET p ; assign SPDEC=CALL p |PUSH p ; assign PTRE=INP p ; assign PTRL=STRP p ; assign PTRINC=INC p ; assign PTRDEC=DEC p ; assign OL=OUT p ; assign INE=IN p |INP p ; assign IRE=CALL p ; assign IRL=CALL p ; assign XL=MULT p ; assign XE=XTDA p ; assign NOTE=LNOT p ; assign ANDE=LAND p ; assign ORE=LOR p ; assign CHENGE=MULT p ; assign CHUE=DIVI p ; assign GAOWEIE=MULT p EMPTY|STP p ; endmodule 这个CPU控制矩阵描述的指令系统,可参考如下指令系统设计: 表 1 参考指令系统 序号 功能设想 助记符16进制操作码2进制操作码 1 把ram存储单元R的内容送到累加器da LDA R 0100000001 2 把ram存储单元R的内容与累加器da的内容相加结果送da ADD R 0200000010 3 用累加器da的内容减去ram存储单元R的内容结果送daSUB R 0300000011 4 将R存储单元内容输出到外设 OUT R 0400000100 5 跳到iram的R单元取指令执行 JMP R 0500000101 6 如果累加器da的值是0则跳到iram的R单元取指令 JZ R 0600000110 7 如果累加器da的值为负则跳到iram的R单元取指令 JN R07 00000111 8 调用iram中R子程序 CALL R 08 00001000 9 输入数据到ram的R存储单元 IN R09 00001001 10 将累加器da的内容送到ram存储单元R STR R 0A 00001010 11 将数N送到累加器da SDA N 0B00001011 12 将累加器da的内容入栈 PUSH 0C00001100 13 将堆栈的内容送到累加器da POP 0D00001101 14 从子程序返回指令 RET 0E00001110 15 将PTR的内容加1INC 0F00001111 16 将PTR的内容减1 DEC 1000010000 17 将da复位为0 ZERO1100010001 18 将数据输入到ptr指示的iram存储单元 INP 1200010010 19 将累加器da的内容送到ptr STRP 1300010011 20 如果输入的数据是h80则跳转到iram的R单元指令 JEND R14 00010100 21 将累加器da内容取反,结果放入da LNOT 1500010101 22 将累加器da与R单元内容作逻辑与,结果放入daLAND R16 00011100 23 将累加器da与R单元内容作逻辑或,结果放入da LOR R 1700010111 24 缓冲区空暂停 STPK 1800011000 25 缓冲区空跳转到R执行 JK R 19 00011001 25 程序输入结束 END 8010000000 26 停机 STP 3F 00111111 参考文献 姜咏江.PMC计算机设计与应用.北京,清华大学出版社,2008.5. 姜咏江.计算机原理教程.北京,清华大学出版社,2005.12. David Money Harrisy.数字设计和计算机体系结构.北京,机械工业出版社,2008.1. 姜咏江.计算机原理综合课程设计.北京,清华大学出版社,2009.6. 注:本文附录提供安装软件。 2009-12-20 生成器安装软件