1. CPU指令集

本书设计的微程序、硬连线和流水线版本 CPU 采用统一的 CPU 指令集,指令的 OP 码如下表 3-1 所示,其格式定义如下:指令 OP 码为指令第一字节的高四位,即指令寄存器IR 的{I7I6I5I4}位。而 RA 和 RB 是指由 I3I2 和 I1I0 定义的逻辑寄存器,RA 或 RB 都可以选择四个物理寄存器(R0~R3)中的任何一个。
表 3-1 微程序版CPU 指令集(OP 码表)

上述指令集总共有 38 条机器指令,可以分成以下五个大类:
一、 系统指令:
系统及中断指令包括三条单字节指令:空指令(NOP)、停机指令(HLT)和中断返回 指令(IRET。其中,NOP 指令主要用于精准延时(微程序/硬连线版 CPU 延时 4 个 T,流 水线版 CPU 延时 1 个 T;而 HLT 指令用作程序末尾 CPU 停机或设置“断点”:程序自动运 行到 HLT 指令时刻停机,可以观察当时 CPU 寄存器,运算器标志位等信息。IRET 指令用于在中断处理子程序末尾返回主程序(即 BP_PC 保存的地址弹回 PC,BP_PSW 保存的标志位信息弹回 PSW,因此,不允许在主程序使用 IRET 指令,否则将导致程序错误跳转。
【注:x 在指令格式说明中表示此处的二进制数值可任意为 0 或 1】
Snipaste_2023-02-24_16-24-26.jpg

二、 寄存器及 I/O 操作指令:
寄存器操作指令包括单字节的寄存器间数据传送指令(MOV)和双字节的寄存器赋值指令(SET。SET 指令的第二字节是赋予寄存器RA 的立即数 IMM。
例:“0110 0001;”表示把 R1 的内容赋值 R0;“0011 0000; 0000 0101;”表示把“05H”赋予 R0。
image.png
I/O 操作指令包括三条单字节指令:输入指令(IN、输出指令(OUT)及地址选择指 令(OUTA。OUTA 指令的功能是把寄存器的内容作为地址输出到 IO 端口的地址选择电路,选择所要操作的外部设备。OUT 指令选定操作的外设后,CPU 可以执行两种操作指令:
IN 指令把外设的数据输入寄存器 RA,OUT 指令则是把寄存器 RA 的内容输出给外设。
【注:IN 指令可以选择 I1I0 指定的四个输入端PORT0~3 中的一个;
而 OUT/OUTA 指令只能选择 I0 指定的两个输出端PORT0~1 中的一个。】例:“0100 0001;”表示把端口 1 的输入数据传送到R0。“0101 0001;”表示把 R0 的内容作为数据,输出到端口 1。“0101 0011;”则是表示把R0 的内容作为地址,输出到端口 1。
image.png
三、 存储器及堆栈操作指令:
存储器操作指令包括两条双字节指令:取数指令(LAD)和存数指令(STO)。LAD指令把数据从地址 ADDR(指令第二字节)的存储器单元取出,存入逻辑寄存器 RA;而 STO 指令把逻辑寄存器 RA 的数据取出,存入地址 ADDR(指令第二字节)的存储器单元。堆栈操作指令包括两条单字节指令:出栈指令(POP)和入栈指令(PUSH)。此处提
到的“堆栈”是基于存储器 ROM/RAM 的“软堆栈”,其指针就是逻辑寄存器 RB。出栈和入栈指令即是把寄存器 RB 存放的内容作为存储器地址,把该地址单元的数据弹出到逻辑寄存器RA(POP 指令)或把逻辑寄存器 RA 的内容弹入到该地址单元(PUSH 指令。
【注:因为 LAD 和 POP 指令共用 OP 码,STO 和 PUSH 指令也共用 OP 码;所以共用 OP码的指令间区别在于 I1I0 指定的内容。LAD 和 STO 指令的 I1I0=00,故 POP 和 PUSH 指令的 I1I0≠00,即其指定的逻辑寄存器 RB(指针)不能选择 R0】例:“1000 0000; 0000 0101;”表示把存储器地址[05H]存放的数据弹出到寄存器R0。“1000 0001;”表示把堆栈指针 R1 指向的地址[R1]存放的数据弹出到寄存器 R0。
image.png

四、 跳转系列指令:
无条件跳转指令 JMP/JMPR 的功能是程序必须跳转到目标地址执行,而有条件跳转指令 Jx/JxR 的功能则是程序是否跳转需要条件判断:当运算器结果标志位 CF(溢出)、ZF(零)或 SF(符号位)为 1 时,程序跳转到目标地址执行;反之,标志位为 0 则程序不跳转,继续顺序执行。根据判断标志位的不同,共有 JC、JZ 和JS 三个有条件跳转指令。跳转系列指令共用 OP 码“0001”,指令的 I3I2 位规定是无条件跳转指令(JMP/JMPR) 还是有条件跳转指令(Jx/JxR)中的一种;而指令的 I1I0 位则指定目标地址是来源于寄存器RB(单字节 JMPR/JxR 指令)还是来源于地址 ADDR 的存储器单元(双字节 JMP/Jx 指令。
【注:双字节跳转指令 I1I0=00,故单字节跳转指令 I1I0 定义的逻辑寄存器 RB 不能选择 R0】例:“0001 0100; 0000 0101;”表示当CF=1 时,程序跳转到第二字节指定的目标地址 05H。“0001 1001;”表示当 ZF=1 时,寄存器 R1 存放数据作为目标地址,程序跳转到该地址。
image.png

五、 算术逻辑运算指令:
单字节移位指令 SHT 可以把逻辑寄存器 RA 中存放的数据向左或向右移动一个位(bit), 移入的位是 0(逻辑移位)或是数据另一端的位(循环移位。四种 SHT 指令共用 OP 码“1010”, 指令的 I0 位指定逻辑移位还是循环移位,而指令的 I1 位则是指定移位的方向。
【注:此处“右移位”指的是寄存器输出 Q3Q2Q1Q0 往小端移动,而“左移位”指的是寄存器输出 Q3Q2Q1Q0 往大端移动,跟时序发生器 74LS194 的“右移”和“左移”的定义相反】
image.png
单字节单操作数运算指令 SOP 可以把寄存器 RA 递增(INC)、递减(DEC)、取反(NOT) 和直通(THR)。如下表所示,四个 SOP 指令共用 OP 码“0010”,由指令 I1I0 位指定具体功能。
【注:THR 指令一般用于根据某个寄存器的数据判断 ZF 和 SF 标志位,从而决定是否跳转】
image.png
双字节双操作数运算指令可以把两个操作数进行算术运算:加法(ADD)、减法(SUB,以及逻辑运算:与(AND、或(OR、异或(XOR。指令的 I1I0 位指定两个操作数全部来自寄存器或是操作数分别来源于寄存器和立即数 IMM(指令第二字节)。前者是单字节指令(ADD、SUB、AND、OR、XOR),后者是双字节指令(ADDI、SUBI、ANDI、ORI、XORI。
【注:双字节指令的 I1I0=00,故单字节指令 I1I0 定义的逻辑寄存器RB 不能选择 R0。】例:“1101 0000; 0000 0101;”表示加法运算“R0=(R0)+05H”。“1101 0001;” 表示加法运算“R0=(R0)+(R1)”。
image.png

2. 微程序版CPU架构

如下图3-1所示,本实验的微程序版CPU由微程序控制器通路(CONTROLLER)、时序电路(CLOCK)及数据通路组成。数据通路包括:程序存储器ROM、数据存储器RAM及通用寄存器R0~R3;IO接口;算术逻辑运算器(74LS181)及附带的移位寄存器(74LS194);程序计数器(PC)、ALU 运算结果标志位寄存器(PSW)及其断点寄存器(BP_PC、BP_PSW)。数据通路的所有部件都共同挂在一条8位系统总线BUS上。
图 3-1 微程序版CPU 电路图
上图3-1中的微程序版CPU架构如下图3-2所示,右侧是时序电路(CLOCK)和微程序控制器(CONTROLLER,左侧则是由8位系统总线BUS串联起来的数据通路,挂在总线BUS上的CPU部件包括:存储器ROM/RAM及其地址寄存器AR;指令寄存器IR;通用寄存器R0~R3;算术逻辑运算器ALU及其附属的缓存器DA(兼作移位功能)和DB;外设I/O接口;程序计数器PC及其断点寄存器(BP_PC;中断向量地址(IVA。此外,数据通路还包括了右边的运算结果标志位寄存器(PSW)及其断点寄存器(BP_PSW)。
图 3-2 微程序版 CPU 架构示意图

2.1 时序电路CLOCK

图 3-3 微程序版CPU 的时序电路
微程序版 CPU 的时序电路如上图 3-3 所示:用红色边框围起来的 CLOCK 电路是 CPU 的基准时钟电路,系统时钟 CLK 可以由方波信号源 AUTO-CLK 提供(双击信号源可以自行选择方波信号频率)或者通过开关 MANUAL 手动步进。当初始化信号 ON=0 或停机指令信号计组课设 - 图13,时钟 CLK 阻塞(强制 CLK=0,CPU 停机。
CLOCK 电路右侧是一个 JK 触发器 74LS73 实现的微指令状态机。由于微程序控制器和数据通路相互独立,两者操作可以并行执行,如下表 3-2 所示。所以,微程序版 CPU 的微指令周期只需要 T1 和 T2 两个状态,时钟信号 CLK 驱动微指令状态机循环输出节拍序列{T1,T2},使状态顺序转移:T1->T2->T1->……
表 3-2 微程序版CPU 的微指令状态机

CLOCK 电路左侧是初始化电路,手动按钮令复位信号image.png上升沿跳变,可以使信号ON=1。CPU 启动仿真后,初始化过程十分简单,如下所述:

  1. 启动仿真后,时钟CLK 选择从手动按钮 MANUAL 输入信号;
  2. 手动按钮使信号计组课设 - 图16跳变“1->0->1”,令信号 ON=1,CLK 允许输出,过程结束。

CLOCK 电路上方是 NOP/HLT 指令电路:当指令寄存器 IR 的 OP 码 I7I6I5I4=0000 的时候,空指令信号 NOP=1,送往微指令计数器;OP 码 I7I6I5I4=0000 且 I0=1 的时候,指令信号计组课设 - 图17,时钟 CLK 阻塞,CPU 停机(陷入“断点”。跳出 HLT 指令“断点”的复位过程与上述初始化过程完全相同,区别在于初始化过程结束后,CPU 进入第一条指令的取指周期 T1 节拍;而复位过程结束后,CPU 进入HLT 指令后续下一条指令的取指周期T1 节拍。
如上图 3-3 所示,为了便于观测程序和微程序的运行,时序电路提供了双位的指令计数器 I 显示当前运行第几条机器指令,以及单位的微指令计数器 MICRO-I 显示当前运行指令计数器 I 所示指令中的第几条微指令。微指令计数器 MICRO-I 由十进制计数器 74LS160 构成,基于信号 ON(初始化过程)或 T1 节拍上升沿驱动递增,在指令周期末尾使能加载信号计组课设 - 图18,在下一个指令周期开始时刻,重置 MICRO-I 的计数值为“1”,重新计数。当以下条件之一成立时,表示当前微指令是指令周期最后一条微指令,令计组课设 - 图19

  1. 当前执行微指令中的判断位P2=1(即计组课设 - 图20);(P 字段请参考“3.1.5 微程序控制器”)
  2. 空指令信号NOP=1 且判断位P1=1(特殊情况:NOP 指令末尾)
  3. 停机信号计组课设 - 图21;( 特殊情况:HLT 指令末尾)

如上图 3-3 所示,当加载信号计组课设 - 图22,下一个指令周期开始的 T1 节拍上升沿令指令计 数信号 ICNT=1,驱动指令计数器 I(由两个计数器 74LS160 级联构成)递增。与此同时, 指令清除信号![](https://cdn.nlark.com/yuque/__latex/8768053e45d5bc02d4b761d44ac1b2ce.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BIR%7D%20%5C%7D%20%5Coverline%7BC%20L%7D%20%5Coverline%7B%5Cmathrm%7BR%7D%7D%3D0%20%5Ctext%20%7B%2C%20%7D&id=AqeXK),即指令周期开始之际,清空指令寄存器 IR。

2.2 微程序控制器

微程序版CPU的微指令结构图如下图3-4所示,微指令字长24位,其中微指令的1-5位是下一条微指令地址,即下址字段[uA4,uA0];微指令的6-8位是判断字段P1~P3微指令的 9-24 位则是微命令字段,对应数据通路的所有微操作信号:其中置“1”的位表示执行相应的微操作;反之,置“0”的位则是不执行相应的微操作
图 3-4 微程序版CPU 的微指令结构图
此外,微指令的15-13 位和12-10 位采用字段编译法(3-8 译码),分别对应源部件输出到总线BUS 和总线BUS 打入目标部件的微操作信号,如下表3-3 所示:
表3-3 微指令字段编译列表

基于上述微指令结构,本实验设计了如下图 3-5 所示的微程序控制器通路,包括三个 8 位 ROM 存储器 2764 组成的微指令存储器 MROM1~3,三个寄存器 74LS273 组成的微指令寄存器 MDR1~3,微指令译码电路,五位微地址寄存器 MA0~MA4 及微地址转移电路。
图 3-5 微程序控制器通路
如下图 3-6 所示, 24 位微指令存储器 MROM1~3 共存放了 32 条微指令,所以微地址是 MABUS4~0。当信号 ON 或 T1 节拍上升沿,微地址下址指定的微指令的微命令字段和 P 字段锁存到微指令寄存器 MDR1~3,输出微操作信号;而下址字段则送往微地址寄存器。
图 3-6 微指令存储器、寄存器及其译码电路
其中,微指令寄存器 MDR2 的输出端采用了两个 3-8 译码器 74LS138 进行字段译码, 分别实现把数据从源部件输出到总线 BUS(译码器 U8)和从总线 BUS 打入目标部件(译码器 U7)的微操作。因为,在任何一条微指令中,仅有一条数据路径,该路径中只有一个源部件把数据打入总线 BUS,其微操作信号互斥;也只有一个目标部件从总线 BUS 接收数据,其微操作信号也是互斥,因此,上述两种微操作信号可以分别用译码器实现。
因为本实验只有 32 条微指令,却需要实现 38 条机器指令。所以部分机器指令需要共用微指令。微指令寄存器 MDR1 的输出译码电路采用了硬连线逻辑来实现以下单操作数指令:递增(INC)、递减(DEC)、取反(NOT)和直通(THR),以及决定算术运算指令所需的CN 操作信号(最低进位,用于补码运算的“求补+1”操作)。
当执行指令 SOP 时,运算器 74LS181 控制端[S3,S2,S1,S0,M,CN]=[0,0,0,0,0,0]。因为
SOP_EN=1,所以 I1 位修改 M ,I0 位修改 S3~S0 和 CN(I4=0,不影响 CN),如下表所示:
image.png
OP 码的 I4 则用来指定双操作数运算指令ADD 和 SUB 的 CN 操作信号,如下表所示:
image.png
此外,为了节省微指令地址,所有的双操作数和单操作数运算指令都在指令执行序列 的第一条微指令就锁存[S3,S2,S1,S0,M,CN],待到最后一条微指令再打入运算器 74LS181 执行,从而得到运算结果输出到总线 BUS。因此,在第一条微指令的微操作信号 DA_CLK 上升沿跳变时刻,把[S3,S2,S1,S0,M,CN]锁存到 74LS374 寄存器 U38;在最后一条微指令周期,微操作信号![](https://cdn.nlark.com/yuque/__latex/8010a851b914b92657cdfefad9cd2eb0.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BAL%7D%7D%20%5Coverline%7BU%7D%20%5C
%5Coverline%7BB%7D%20%5Coverline%7BU%7D%20%5Coverline%7BS%7D%3D0&id=yC3bC) 使能 74LS374 输出[S3,S2,S1,S0,M,CN]执行,再得到运算结果。
图 3-7 微地址转移电路
本实验的微地址转移电路如上图3-7所示,微地址寄存器五位(MA4-MA0),由触发器74LS74组成。T2时刻,当前微指令1-5位的下一条微指令地址[uA4,uA0]打入微地址寄存器;此刻,若当前执行的微指令中的判断位P1~P3置位,则地址转移逻辑电路将根据判断位P1~P3置位微地址寄存器MA4-MA0,如上图3-7所示:P2位生成信号计组课设 - 图30,P1生成信号计组课设 - 图31,P1和P3位共同生成信号计组课设 - 图32。判断位P1~P3的地址跳转逻辑如下所示(可以对照后面具体指令流程图中“菱形框”的条件判断分支过程):
P1 逻辑:若当前微指令是机器指令取指周期的最后一条微指令,则判断位P1=1,从而根据指令寄存器IR 的I7I6I5I4位强制置位微地址寄存器的MA3-MA0,修改微地址[uA3,uA0]位,转向该机器指令的执行周期序列的第一条微指令地址[0I7I6I5 I4]。
P2 逻辑:若当前微指令是机器指令执行周期的最后一条微指令,则判断位P2=1,此时若无中断发生,则返回取指周期第一条微指令地址[00000];若有中断发生(INT=1),则强制置位微地址寄存器的MA4,转向中断处理过程第一条微指令地址[10000]。
P3 逻辑:在CPU 指令集中部分单字节指令和双字节指令(LAD/POP、STO/PUSH、ALU 系列和JMP 系列指令)共用OP 码,其执行周期的微指令序列共用第一条微指令(判断位P3=1,从第二条微指令开始分支,根据指令寄存器IR 的I1I0位来决定不同微指令的分支走向:若I1I0=00,微指令下址的MA0=0,操作数分别来自寄存器和存储器(双字节指令;若I1I0≠00,则微指令下址的MA0=1,操作数全部来自寄存器(单字节指令)。

2.3 取指及中断处理过程

除了空指令(NOP)和停机指令(HLT)以外,所有的CPU 指令都包括了取指周期和执行周期。因为NOP 指令OP 码为“0000”,所以取指周期末尾P1(0I7I6I5I4)译码的时候,直接返回取指周期(取下一条指令),没有执行周期。而HLT 指令与NOP 指令完全相同,唯一不同是在取指周期后CPU 硬件停机,需要手动RESET“重启”才能跳出停机状态,进入下一条指令。此外,外部中断触发后,中断处理周期有专用的微指令使程序转向中断子程序。待到中断子程序末尾,最后一条指令必须是中断返回指令(IRET),才能返回主程序。
图 3-8 取指周期、中断处理周期及系统指令的微程序流程图
上图3-8 所示是取指周期、中断处理周期及NOP、HLT、IRET 指令的微程序流程图,其中每个方框在时间上表示一个微指令周期,包括 T1 和 T2 两个节拍;在空间上表示数据从某个源部件经过总线 BUS 到达另一个目标部件的路径。每个方框的右上方是该微指令在控制存储器中的地址,右下方则是下一条微指令的地址。下表 3-4 则列出了上图 3-8 所对应的取指周期(即NOP/HLT 指令)、中断处理周期及 IRET 指令的微指令代码:
表 3-4 微指令代码表(取指周期、中断处理周期及 IRET 指令)
本实验设计的存储器地址总线8位,地址空间256字节(00H~FFH)。分配其中低半区(00H~7FH)为ROM存储区(128 字节),高半区(80H~FFH)为RAM存储区(128 字节,如下图3-9所示,存储器ROM和RAM共用一个地址寄存器AR,两个存储器共用计组课设 - 图35信号作为存储器读信号,由地址最高位A7 来作为两个存储器的片选信号。RAM存储器是可读写存储器,存放临时的数据。而 ROM是只读存储器,存放程序和常量(采用堆栈操作指令访问)。因此,CPU程序和常量的存储容量最大是 128字节,若程序和常量的代码量超过了128 字节,则会越界出错。同样的,因为只有存储器RAM 允许写入,所以当存储器写信号计组课设 - 图36 的时候,只有地址范围[80H,FFH]是允许写入操作的;对地址范围[00H,7FH]的存储器单元进行写入操作是非法的。值得注意的是,上述存储器不同地址范围的读写差异必须由通过软件(程序员或汇编器)来判别。
图 3-9 存储器(ROM/RAM)及指令寄存器 IR 电路
存储器ROM(存放程序和常量)和RAM(存放数据)共用地址寄存器AR,而程序计数器PC 和AR 并联挂到总线BUS。因此,如上图3-9 和下图3-10 所示,取指周期需要两条微指令(即两次路径):第一条微指令[00000]的 T1 时刻,PC 输出当前指令地址到总线BUS(计组课设 - 图38,T2 时刻由ARCLK 上升沿打入存储器地址寄存器AR;第二条微指令T1 时刻,程序存储器ROM 输出指令(计组课设 - 图39)到总线BUS,在T2 时刻由IR_CLK 上跳沿打入指令寄存器IR;并且PC+1(PC_CLK 上升沿)。
图 3-10 程序计数器PC、断点BP_PC 及中断向量地址电路
本实验的CPU中断电路采用单级中断机制,不允许中断嵌套;同时,CPU 采用中断向量表的形式保存中断向量 Vector(即中断子程序入口地址。如下图3-11所示,中断子程序的位置和长度随意设置,子程序的首地址(即中断向量 Vector)必须放在中断向量表中。中断发生时,CPU通过二次寻址跳转到中断子程序执行。如上图3-10所示,进入中断处理周期的第一条微指令[10000]后,在T1 时刻,INTR=1 的上升沿跳变把PC的当前值保存到断点寄存器BP_PC;同时,计组课设 - 图41令拨码开关设置的中断向量地址VTR_ADDR 输出到总线BUS,并在T2 时刻上升沿打入存储器地址寄存器AR。在中断处理周期第二条微指令的T1 时刻,存储器输出Vector 到总线BUS,并且在T2 时刻打入PC。
图 3-11 中断向量表示意图
如下图 3-12(右)所示,采用按钮来模拟 CPU 的外部中断,其按下的时候将产生一个上 升沿跳变,输出 INT=1。所有指令的执行周期末尾必须执行 P2(INT)判断:若 INT=1, 表 示在当前指令周期有中断触发,则 P2 置位MA4=1,即微指令下址[uA4, uA0]= [10000], 进 入中断处理周期;若 INT=0,表示没有中断,则返回取指周期(取下一条机器指令。在中断处 理周期的第一条微指令[10000]中,INTR=1 清零 INT,并且把中断触发电路的输入(U31:A 反向输出端)锁死在低电平 0,即在中断子程序中不允许再次触发中断。如下图 3-12(左) 所示,INTR=1 上升沿跳变把标志位寄存器 PSW 的内容保存到 PSW 断点寄存器 BP_PSW 中,进而在 T2 时刻把寄存器 PSW 清零,即主程序标志位不影响中断子程序。
图 3-12(左) 断点 BP_PSW 及中断触图 3-12(右) 断点 BP_PSW 及中断触
IRET 指令则是一个与中断处理周期相反的过程:如上图 3-10 所示,计组课设 - 图45 把断点寄 存器 BP_PC 保存的“断点”输出到总线 BUS,然后在 T2 时刻打入 PC 中。类似的,如上图 3-12(左)所示,断点寄存器 BP_PSW 保存的“断点”输出,把数据通路的标志位输出缓冲器 U37:A 禁止,然后在 T2 时刻恢复到标志位寄存器 PSW 中(注:在主程序中是由运算结果输 出信号![](https://cdn.nlark.com/yuque/__latex/52afb89f56519494116b325f85da4285.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BALU%7D%7D%20%5C
%20%5Coverline%7B%5Cmathrm%7BB%7D%7D%20%5Coverline%7B%5Cmathrm%7BU%7D%7D%20%5Coverline%7B%5Cmathrm%7BS%7D%7D%3D0&id=BnGdx)在 T2 时刻把标志位打入 PSW。最后,如上图 3-12(右)所示,在 IRET 指 令结束返回主程序后,计组课设 - 图46 产生的上升沿把中断触发电路输入(U31:A 的反向输出端) 置为高电平 1,令中断触发电路恢复正

2.4 寄存器及 I/O 操作指令

寄存器操作指令包括一条单字节的寄存器间传送指令(MOV)和一条双字节的寄存器 赋值指令(SET);I/O 操作指令包括三条单字节指令:输入指令(IN)、数据输出指令 (OUT)及地址输出指令(OUTA) 下图 3-13 是 MOV、SET 指令和 IN、OUT/OUTA 指令 的微程序流程图,其中(P1 判断前)取指周期和若有中断触发的(P2 判断后)中断处理周 期参见上图 3-8。此外,OUT 和 OUTA 指令的微指令序列完全相同,由硬件逻辑区分。
图 3-13 寄存器及 I/O 操作指令的微程序流程图
下表 3-5 列出了上图 3-13 对应的寄存器操作指令 MOV、SET 及 I/O 操作指令 IN、 OUT/OUTA 的微指令代码。
表 3-5 微指令代码表(MOV/SET/IN/OUT 指令)
图 3-14(左) 通用寄存器 R3 及寄存器选择电路图
图 3-14(右) 通用寄存器 R3 及寄存器选择电路图
如上图3-14(左)所示,CPU 共有四个并列的通用寄存器 R0~R3,因为在上述 CPU 指令 中,指令执行的操作数来源可能是逻辑寄存器 RA 或RB 的输出,但是指令执行的结果只能 是打入寄存器RA。所以,在上图3-14(右)中,微操作信号计组课设 - 图51计组课设 - 图52分别根据指令 的 I3I2 位和I1I0 位选择通用寄存器(R0~R3)之一输出操作数(注:微操作信号计组课设 - 图53计组课设 - 图54不允许出现在同一个微指令中,避免出现冲突);而微操作信号计组课设 - 图55则直接根据指令的。
图 3-15(左) 外围设备及 IO 接口电路图
图 3-15(右) 外围设备及 IO 接口电路图
上图3-15 所示是CPU 的IO 接口外挂设备,采用拨码开关 DSW1 模拟输入设备,数码显示 管模拟输出设备。若当前运行IN 指令,则信号计组课设 - 图58, 外围设备输入数据到BUS 总 线。在 上图3-14(右)中,根据IN 指令的I1I0 位产生IO 输入使能信号 计组课设 - 图59,可以指定4 个输入 设备,同样的,若当前运行 OUT/OUTA 指令,则信号 计组课设 - 图60, BUS 总线输出数据到IO 接口 外围设备,根据指令的IO位产生IO 输出使能信号 计组课设 - 图61 ,可以指定2个输 出设备,而指令的I1 位作为地址锁存信号ALE。 若 ALE=1,则输出地址(OUTA 指令);若 ALE=0,则输出数据(OUT 指令),如上图3-15(右)所示。注意:计组课设 - 图62 信号是打入目 标部件的使能信号,时序须与其它打入信号保持一致,仅在 T2 周期有效

2.5 存储器及堆栈操作指令

双字节存储器操作指令包括了取数指令 LAD 和存数指令 STO,而单字节堆栈操作指 令包括了出栈指令 POP 和入栈指令 PUSH,下图 3-16 是存储器操作指令 LAD、STO 和堆栈 操作指令 POP、PUSH 的微程序流程图。从图中可以看出,POP 指令只需要[11011]和 [11101]两条微指令就够了,但是为了节省 OP 码,POP 和LAD 指令共用 OP 码“1000”,即共 用第一条微指令[01000](即使 POP 指令其实并不需要微指令[01000])。从而可以在第一条微 指令的末尾采用 P3(I1I0)判断LAD 和POP 指令的不同路径:若 I1I0=00,执行直接根据第二字节 目标地址 ADDR 从存储器取数的双字节 LAD 指令;若 I1I0≠00,则执行根据逻辑寄存器 RB (R1~R3)内容指定的目标地址从存储器取数的单字节 POP 指令。STO 和 PUSH 指令的关系类似 LAD 和 POP 指令。
图 3-16 存储器及堆栈操作指令的微程序流程图
下表 3-6 列出的存储器指令 LAD/STO 和堆栈指令 POP/PUSH
表 3-6 微指令代码表(LAD/POP/STO/PUSH 指令)
JMPCLR和![](https://cdn.nlark.com/yuque/__latex/77e663c820932b567556060bf2b8f8ba.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BL%7D%7D%20%5Coverline%7B%5Cmathrm%7BO%7D%7D%20%5Coverline%7B%5Cmathrm%7BA%7D%7D%20%5Coverline%7B%5Cmathrm%7BD%7D%7D%20%5C%5Coverline%7B%5Cmathrm%7BP%7D%7D%20%5Coverline%7B%5Cmathrm%7BC%7D%7D&id=exOnk)的逻辑“与”来决定是否运行PC_CLK=1(即PC+1操作)。

2.6 跳转系列指令

下图 3-17 是 JMPR/JxR 指令和 JMP/Jx 指令的微程序流程图。从图中可以看出,
JMPR/JxR 指令只需要[11111]微指令就够了,但是为了节省 OP 码,两条跳转指令共用 OP 码“0001”,即共用第一条微指令[00001](即使 JMPR/JxR 指令其实并不需要 [00001] 微指令)。从而可以在第一条微指令的末尾采用 P3(I1I0)区分两种跳转指令的不同路径:若I1I0=00,执行直接根据第二字节目标地址 ADDR 跳转的双字节 JMP/Jx 指令;若 I1I0≠00, 则执行根据逻辑寄存器RB(R1~R3)内容指定的目标地址跳转的单字节JMPR/JxR 指令。
图 3-17 跳转系列指令的微程序流
下表 3-7 列出了单字节跳转指令 JMPR/JxR 和双字节跳转指令 JMP/Jx 的微指令代码
表 3-7 微指令代码表(JMP/JMPR/Jx/JxR 指令
下图 3-18(左)所示,跳转指令“0001”执行的时候,微操作信号计组课设 - 图67首先根据指令的I3I2 位译码,判断是执行无条件跳转指令(微操作信号计组课设 - 图68)还是有条件跳转指令 JC、JZ 和 JS(对应的微操作信号J¯x=0)。若执行有条件跳转指令,还需要根据标志位寄存器PSW 保存的运算器标志位 CF/ZF/SF 来断定是否生成微操作信号计组课设 - 图69,使得跳转发生。值得注意的是,在有条件跳转指令 JCR、JZR、JSR 的执行周期最后一条微指令[11111]处,倘若最后不跳转,则因为 JxR 是单字节指令。所以,此处不但需要不打入 PC,而且还必须禁止 PC+1 。因此, 只有在地址[11111] 的微指令执行的时候, 使用微操作信号 JMP_CLR 和 LOAD_PC 的逻辑“与”来决定是否运行 PC_CLK=1(即 PC+1 操作)。
图 3-18(左) 跳转系列指令和运算指令的硬件译码逻辑电路图图 3-18(右) 跳转系列指令和运算指令的硬件译码逻辑电路图

2.7 算术逻辑运算系列指令

图 3-19 算术逻辑运算系列指令的微程序流程图
术逻辑运算系列指令包括了单字节的移位指令 SHT,单字节单操作数运算指令 SOP, 以及五条单字节的双操作数运算指令(ADD/SUB/AND/OR/XOR)和五条双字节的双操作数运算指令(ADDI/SUBI/ANDI/ORI/XORI),其微程序流程图如上图 3-19 所示。为了节省微指令,所有的运算指令都在第一条微指令期间锁存 74181 运算器的控制端逻辑 [S3,S2,S1,S0,M,CN]。此外,五种双操作数的运算指令都采取在第一条微指令的末尾采用P3(I1I0)判断双字节和单字节指令的不同路径:若 I1I0=00,执行操作数分别来自逻辑寄存器RA 和指令第二字节(立即数 IMM)的双字节指令;若 I1I0≠00,则执行操作数全部来自寄存器的单字节指令。上述算术逻辑运算指令的微指令代码表如下表 3-8 所示:
表 3-8 微指令代码表(SHT、SOP 及双操作数运算指令)
值得注意的是,单操作数运算指令 SOP 只有一条微指令[00010]。必须由上图 3-18(右) 所示的硬件逻辑电路根据 SOP 指令的 I1I0 位修改运算器控制端[S3,S2,S1,S0,M,CN],实现递增(INC)、递减(DEC)、取反(NOT)、直通(THR)四个功能。同时,OP 码的 I4 位则用来指定双操作数算术运算指令ADD 和 SUB 的 CN 操作信号,如下所示:
图 3-20 运算器ALU 通路
图 3-20 运算器ALU 通路
上图 3-20(左)所示运算器 ALU 通路,运算器 74LS181 除了输出结果到总线 BUS, 还输出运算结果的标志位 CF(溢出)、ZF(零)、SF(符号位)到标志位寄存器 PSW 保存。上图 3-20(右)所示是运算器 ALU 的缓存器 DA 和 DB。其中 DB 采用寄存器74LS273,而 DA 则采用移位寄存器 74LS194,兼有缓存和移位功能。当微操作信号 计组课设 - 图76 的时候(非 SHT 指令),74LS194 的状态{S0,S1}={1,1},工作模式强制为送数, DACLK 上升沿跳变把 74LS194 输入端 D3D2D1D0 保存到输出端 Q3Q2Q1Q0 ; 当 ![](https://cdn.nlark.com/yuque/__latex/e71b72a8c9937ca0cb68b35d687d702c.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BSHT%7D%7D%5C%5Coverline%7B%5Cmathrm%7BEN%7D%7D%3D0&id=Oc8Pz) 的时候(SHT 指令),移位寄存器 74LS194 的状态{S0,S1}由指令 SHT 的 I1 位决定。若 I1=0,{S0,S1}={0,1},则寄存器输出端 Q3Q2Q1Q0 往 Q0 端移动,即右移;若 I1=1, {S0,S1}={1,0},则寄存器输出端 Q3Q2Q1Q0 往 Q3 端移动,即左移。而 SHT 指令的 I0 位则决定是逻辑移位还是循环移位:若 I0=0,则 74LS194 的输入端 SL=SR=0,即逻辑移位;若IO=1,则 74LS194 的输入端 SL 和 SR 分别接 74LS194 的另一端,即循环移位。缓存寄存器 DA 和 DB 的打入微操作信号 DA_CLK 和 DB_CLK 分别在三种情况下触发:

  1. 双操作数运算指令:操作数全部来源于逻辑寄存器 RA 和 RB,DACLK 和 DB_CLK 分别由微操作信号![](https://cdn.nlark.com/yuque/__latex/995e9043907fc05f248c01ad63380a4d.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BRA%7D%7D%5C%5Coverline%7B%5Cmathrm%7BBUS%7D%7D&id=bCsqr)和计组课设 - 图77驱动;
  2. 双操作数运算指令:操作数之一来自指令第二字节(立即数 IMM),则 DACLK 由微 操作信号![](https://cdn.nlark.com/yuque/__latex/995e9043907fc05f248c01ad63380a4d.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BRA%7D%7D%5C%5Coverline%7B%5Cmathrm%7BBUS%7D%7D&id=zOWFO)驱动,而微指令[11100]期间,DBCLK 则由微操作信号![](https://cdn.nlark.com/yuque/__latex/4a9c15f6f2bb6f8562edc9249ef424c9.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BMEM%7D%7D%5C%5Coverline%7B%5Cmathrm%7BOE%7D%7D&id=XfRQS)驱动;
  3. 移位指令 SHT:在微指令[10011]期间,DA 缓存器 74LS194 移位需要再次 DACLK 上升沿跳变才能实现,则DA_CLK 由微操作信号![](https://cdn.nlark.com/yuque/__latex/5231dbd756a11ff0a6b05566bf967ae2.svg#card=math&code=%5Coverline%7B%5Cmathrm%7BSHT%7D%7D%5C%5Coverline%7B%5Cmathrm%7BEN%7D%7D&id=f9kcs)驱动。

3. 详细设计

3.1 模型机指令系统

表 - 1

助记符 功能 格式
NOP; 空指令/延时4个T 0000 XX XX
HLT; 停机 0000 00 01
RLC RA; (RA)右逻辑移位->RA 1010 RA 00
LLC RA; (RA)左逻辑移位->RA 1010 RA 10
RRC RA; (RA)右循环移位->RA 1010 RA 01
LRC RA; (RA)左循环移位->RA 1010 RA 11
LAD RA, [ADDR]; [ADDR]->RA 1000 RA 00
ADDR
POP RA, [RB]; [RB]->RA 1000 RA RB
STO RA, [ADDR]; RA->[ADDR] 1001 RA 00
ADDR
PUSH RA, [RB]; RA->[RB] 1001 RA RB
ADD RA, RB; (RA)+(RB)->RA 1101 RA RB
ADDI RA, IMM; (RA)+IMM->RA 1101 RA 00
IMM
SUB RA, RB; (RA)-(RB)->RA 1100 RA RB
SUBI RA, IMM; (RA)- IMM ->RA 1100 RA 00
IMM
AND RA, RB; (RA) ∧(RB)->RA 1110 RA RB
ANDI RA, IMM; (RA) ∧IMM->RA 1110 RA 00
IMM
XOR RA, RB; (RA) ⊕(RB)->RA 1011 RA RB
XORI RA, IMM; (RA) ⊕IMM->RA 1011 RA 00
IMM
OR RA, RB; (RA)∨(RB)->RA 1111 RA RB
ORI RA, IMM; (RA)∨IMM->RA 1111 RA 00
IMM
JMPR [RB]; [RB] ->PC 0001 00 RB
JMP ADDR; ADDR->PC 0001 00 00
ADDR
JZR [RB]; IF ZF=1, [RB] ->PC 0001 10 RB
JZ ADDR; IF ZF=1, ADDR->PC 0001 10 00
ADDR
JCR [RB]; IF CF=1, [RB] ->PC 0001 01 RB
JC ADDR; IF CF=1, ADDR->PC 0001 01 00
ADDR
JSR [RB]; IF SF=1, [RB] ->PC 0001 11 RB
JS ADDR IF SF=1, ADDR->PC 0001 11 00
ADDR
SET RA, DATA; DATA->RA 0011 RA XX
DATA
INC RA; (RA)+1->RA 0010 RA 00
DEC RA; (RA)-1->RA 0010 RA 01
NOT RA; #(RA) ->RA 0010 RA 10
THR RA; (RA)->RA 0010 RA 11
IN RA, Px; (PORTx)->RA 0100 RA PORTx
OUT RA, Px; RA->(PORTx) 0101 RA 0/PORTx
OUTA RA, Px; RA->(PORTx) 0101 RA 1/PORTx
MOV RA, RB; RB->RA 0110 RA RB
IRET; 中断返回 0111 XX XX

PS:

  1. XX: 表示任意
  • RA\RB: 表示寄存器(实际在写程序的时候,不是用RA表示第一个寄存器,而是用R1表示第一个寄存器,如MOV 3,R1;)
  • ADDR: 表示地址
  • DATA:表示数据,如 MOV 3,R1;,这里的3就是DATA
  1. 指令PUSH/POP和JMP系列指令的JMPR/JCR/JZR/JER的RB只能是R1\R2\R3,不能是R0
  2. IN和OUT指令的汇编要指明是对哪个外设端口操作,外设定义了四个端口 PORT0-3;其中PORT0和1 是双向端口 即IN 和OUT都能操作的,PORT 2和3 是单向输入端口 只有IN指令。
  • IN指令的【IR1,IR0】指明操作的是哪个外设PORTx
  • OUT指令的IR0指明操作的外设PORTx,IR1指明传送外设的内容是数据还是地址(即IR1=0相当于ALE=0,向外设发送数据;IR1=1相当于ALE=1,向外设发送地址)。
  1. HLT指令改为跟NOP指令相同OP码,然后IR0=1是停机,IR0=0是NOP指令

    3.2 新增指令系统

    表 - 1为课程设计所给的基本模型机指令系统,我们直接在这个基本指令系统的基础上进行了扩展。下表为新增的指令。
助记符 功能 格式
CMP RA,RB; (RA)-(RB) 1100 RA RB
JNS ADDR; IF SF!=1, ADDR->PC 0001 10 00
ADDR
JNZ ADDR; IF ZF=1, ADDR->PC 0001 10 00
ADDR ADDR
JNC ADDR; IF CF=1, ADDR->PC 0001 01 00
ADDR ADDR
XCHG (RA)->RB,(RB)->RA 1100 01 xx

1. CMP指令微指令设计

(1) CMP/SUB指令区别和联系

CMP指令和SUB指令的共同点都是做减法、设置标志位SF、ZF、CF;区别是SUB指令会改变目的操作数RA的值,而CMP指令不改变目的操作数RA的值,只设置标志位。见下表

SUB RA,RB (RA)-(RB)->RA、设置标志位
CMP RA,RB (RA)-(RB)、设置标志位

(2) CMP指令设计思路和执行流程图

计组课设 - 图78

(3) CMP指令微指令设计方法

① 修改表11第3条微指令,把001改成000,不发T2:BUS->RA信号。

image.png 微指令 入口地址 微操作




01100000 00011100 00111000




[01100]
取出减法指令,根据[0I7I6I5I4]得到微指令地址[01100]
[15..13]是001完成T1:RA->BUS
[12..10]是110完成T2:BUS->DA
[24..20]是01100设置S3~S3、M
[6]是1,减法指令是单字节,置微指令最低位为1,下一条微指令入口地址[11001]
00000000 01011100 00010100 [11001] 根据入口地址[11001]取出第二条微指令
[15..13]是101完成T1:RB->BUS
[12..10]是110完成T2:BUS->DB,
下一条微指令入口地址[10100]


00000000 00110010 01000000

00000000 00110000 01000000
[10100] 完成减法运算
[15..13]是011完成T1:ALU->BUS,设置标志位
[12..10]是000,跳过T2:BUS->RA
[7]判断中断,有中断转中断处理

[00000] 无中断取下一条指令

② 把“排序微指令集.txt”的第21行,即入口地址为[10100]的微指令第2个字节00110010→00110000,产生新文件“CMP替换SUB排序微指令集.txt”,内容如下: :::tips EPROM1 EPROM2 EPROM3
00000000 01001000 00010101 取址(NOP) [00000] 取址(NOP_HLT)1
00000000 01001000 00111110 JMP [00001] JMP1
00000100 00011100 00010100 SOP [00010] SOP1
00000000 01001000 00010010 SET [00011] SET1
00000000 01100010 01000000 IN [00100] IN1
00000000 00010110 01000000 OUT [00101] OUT1
00000000 01010010 01000000 MOV [00110] MOV1
00000000 11111110 01000000 IRET [00111] IRET1
00000000 01001000 00111010 LAD [01000] LAD1
00000000 01001000 00110110 STO [01001] STO1
11111000 00011100 00010011 SHT [01010] SHT1
01101000 00011100 00111000 XOR [01011] XOR1
01100000 00011100 00111000 SUB [01100] SUB1
10010000 00011100 00111000 ADD [01101] ADD1
10111000 00011100 00111000 AND [01110] AND1
11101000 00011100 00111000 OR [01111] OR1

00000001 00001000 00011110 中断响应 [10000] 中断响应1
00000000 00011010 01000000 [10001] STO3
00000000 10100010 01000000 [10010] SET2
11111010 00001100 00010100 [10011] SHT2
00000000 00110000 01000000 [10100] ADD\SUB\AND\OR\XOR 4(case1)3(case2)\SOP2\SHT3
00000000 10100100 10000000 [10101] 取址(NOP)2
00000000 10101000 00010001 [10110] STO2 case1
00000000 01011000 00010001 [10111] STO2 case2
00000000 01001000 00011100 [11000] ADD\SUB\AND\OR\XOR 2(case1)
00000000 01011100 00010100 [11001] ADD\SUB\AND\OR\XOR 2(case2)
00000000 10101000 00011101 [11010] LAD2 case1
00000000 01011000 00011101 [11011] LAD2 case2
00000000 10101100 00010100 [11100] ADD\SUB\AND\OR\XOR 3(case1)
00000000 00100010 01000000 [11101] LAD3
00000000 10101110 01000000 [11110] 中断响应2\JMP2 case1
00000000 11011111 01000000 [11111] JMP2 case2 :::

③ EPROM1.ASM、EPROM3.ASM不用修改,只需修改EPROM2.ASM的21行为00110000B,并重新汇编覆盖原EPROM2.HEX文件。

(4) 测试

一.测试准备
把EPROM2.HEX重新装入模型计算机的存储器EPROM2。
二.CMP指令测试
使用了2个程序进行测试,这2个程序分别测试了R0=4、R1=3和R0=3、R1=4两种情况。程序在不改变2个寄存器值的情况下实现了2个数据比较,输出大数,说明CMP指令设计正确。
注:程序中虽然使用了SUB标识符,但是对应的微指令已经是CMP功能。

测试程序1:JS.ASM ORG 0000H DB 00110000B ;SET R0,04H DB 00000100B ; DB 00110100B ;SET R1,03H DB 00000011B ; DB 00000001B ;HLT DB 11000001B ;SUB R0,R1 DB 00011100B ;JS 0BH DB 00001011B ; DB 01010000B ;OUT R0,PORT0 DB 00010000B ;JMP 0CH
DB 00001100B ;
DB 01010100B ;OUT R1,PORT0
DB 00000001B ;HLT
END

注释:
表12

地址 目标码 指令 说明
0 00110000B SET R0,04H R0=04
1 00000100B

2 00110100B SET R1,03H R1=03
3 00000011B

4 00000001B HLT 断点1,观察R0和R1,按RESET按钮继续执行
5 11000001B SUB R0,R1 R0-R1,此例设置SF(是负数?是负数设置标志为1,不是负数设置标志为0)标志为0
6 00011100B JS 0BH (IF SF=1, ADDR->PC)R0<R1转到0BH,输出R1,否则顺序执行
7 00001011B

8 01010000B OUT R0,PORT0 R0>R1,输出R0
9 00010000B JMP 0CH
0A 00001100B

0B 01010100B OUT R1,PORT0
0C 00000001B HLT

执行结果:尽管使用了减法,但是R0、R1执行前后保持不变。

R0 image.png
R1 image.png
输出 image.png

图5

测试程序2:JS1.ASM ORG 0000H DB 00110000B ;SET R0,03H DB 00000011B ; DB 00110100B ;SET R1,04H DB 00000100B ; DB 00000001B ;HLT DB 11000001B ;SUB R0,R1 DB 00011100B ;JS 0BH DB 00001011B ; DB 01010000B ;OUT R0,PORT0 DB 00010000B ;JMP 0CH
DB 00001100B ;
DB 01010100B ;OUT R1,PORT0
DB 00000001B ;HLT
END

注释:
表13

地址 目标码 指令 说明
0 00110000B SET R0,03H R0=03
1 00000011B

2 00110100B SET R1,04H R1=04
3 00000100B

4 00000001B HLT 断点1,观察R0和R1,按RESET按钮继续执行
5 11000001B SUB R0,R1 R0-R1,此例设置SF(是负数?是负数设置标志为1,不是负数设置标志为0)标志为1
6 00011100B JS 0BH (IF SF=1, ADDR->PC)R0<R1转到0BH,输出R1,否则顺序执行
7 00001011B

8 01010000B OUT R0,PORT0 R0>R1,输出R0
9 00010000B JMP 0CH
A 00001100B

B 01010100B OUT R1,PORT0
C 00000001B HLT

执行结果:尽管使用了减法,但是R0、R1执行前后保持不变。

R0 image.png
R1 image.png
输出 image.png

注意:修改SUB指令后会影响ADD/OR/XOR/AND等指令,不能使用这些指令编程。可以考虑对原指令系统进行精简以满足设计新指令的需要。

2. JNS/JNZ/JNC指令微指令设计

(1) JNS/JNZ/JNC指令设计思路和执行流程图

计组课设 - 图86

(2) JNS/JNZ/JNC指令微指令设计方法

参考JS/JZ/JC设计方法
计组课设 - 图87

image.png 微指令 入口地址 微操作




0000 0000 0100 1000 0011 1110




[00001]
取出减法指令,根据[0I7I6I5I4]得到微指令地址[01100]
[15..13]是100完成T1:PC->BUS
[12..10]是110完成T2:BUS->AR
下一条微指令入口地址[11111]
0000 0000 1101 1111 0100 0000 [11111] 根据入口地址[11111]取出第二条微指令
[15..13]是101完成T1:RB->BUS
[12..10]是111完成T2:BUS->PC,
下一条微指令入口地址[00000]

[00000] 无中断取下一条指令

JMPR/JxR 指令只需要[11111]微指令就够了,但是为了节省 OP 码,两条跳转指令共用 OP 码“0001”,即共用第一条微指令[00001](即使 JMPR/JxR 指令其实并不需要 [00001] 微指令)。从而可以在第一条微指令的末尾采用 P3(I1I0)区分两种跳转指令的不同路径:若I1I0=00,执行直接根据第二字节目标地址 ADDR 跳转的双字节 JMP/Jx 指令;若 I1I0≠00, 则执行根据逻辑寄存器RB(R1~R3)内容指定的目标地址跳转的单字节JMPR/JxR 指令。

程序JNS1.ASM
ORG0000H
DB 00110000B ;SET R0,04H
DB 00000100B ;
DB 00110100B ;SET R1,03H
DB 00000011B ;
DB 11000001B ;SUB R0,R1
DB 00011100B ;JNS 0AH
DB 00001010B ;
DB 01010000B ;OUT R0,PORT0
DB 00010000B ;JMP 0BH
DB 00001011B ;
DB 01010100B ;OUT R1,PORT0
DB 00000001B ;HLT
END
注释:

地址 目标码 指令 说明
0 00110000B SET R0,04H R0=04
1 00000100B

2 00110100B SET R1,03H R1=03
3 00000011B

4 11000001B SUB R0,R1 R0-R1→R0,R0=4-3=1
5 00011100B JNS 0AH R0>R1转到0AH,输出R0
6 00001010B

7 01010000B OUT R1,PORT0 数码管显示
8 00010000B JMP 0BH 转到0DH结束
9 00001011B

A 01010100B OUT R0,PORT0
B 00000001B HLT 断点2,结束。观察R0和R1

执行后R0=1,R1=3,显示R0

R0 image.png
R1 image.png
输出 image.png

3. XCHG

交换2个寄存器值指令
1.指令格式:XCHG RA,RB
2.套用SUB的格式和入口地址,即操作码和SUB相同。RA可以是R0~R3,RB只能是R1~R3,因为R0经过汇编后为00是带立即数减法。
3.图1是交换2个寄存器值过程。
图1
① RA→BUS,BUS→DA(可参考SUB指令)
② RB→BUS,BUS→RA(可参考MOV指令)
③ 利用逻辑运算F=A,DA→ALU→BUS, BUS→RB。F=A的S3~S0、M设置是11111。

4.电路修改
④ 表1解释了为什么增加LDRB
利用“BUS->”字段的第一行空闲“000”增加写入RB信号LDRB
表 1 微指令字段编译列表

在工程里增加3个位置电路图,分别见图1~图3。
① 74LS138的Y0原来是空的,增加LDRB,“BUS->”字段是000
② 当LDRB为0时,根据图2选择R1~R3
③ 在图2的写入R1~R3各增加一个与门,只要LDRB和LDR任何一个有效即可利用LDR写入RA、利用LDRB写入RB。
图1
图2
图3

5.微信号编写
① 依照减法指令修改微信号见表1
表1
具体修改:
根据入口地址[01100]得知[01100]=12,在EPRROM中是第13行;
根据入口地址[11001]得知[11001]=25,在EPRROM中是第26行;
根据入口地址[10100]得知[10100]=20,在EPRROM中是第21行;

打开文件EPROM1.ASM、EPROM2.ASM、EPROM3.ASM,对照表1分别修改第13、26、21行,保存,汇编。
微指令集.txt和排序微指令集.txt可以不改,机器不识别这2个文件。

6.测试程序XCHG.ASM
ORG 0000H
DB 00110000B ;SET R0,04H
DB 00000100B ;
DB 00110100B ;SET R1,03H
DB 00000011B ;
DB 11000001B ;SUB R0,R1,实际上是XCHG R0,R1
DB 01010100B ;OUT R1,PORT0
DB 00000001B ;HLT
END
执行前R0=4,R1=3,显示R0

R0 image.png
R1 image.png
输出 image.png

执行后R0=3,R1=4,显示R1

R0 image.png
R1 image.png
输出 image.png