











- 0100,数据读入寄存器
- 0001,数据与寄存器相加,结果保存到寄存器
- 0010,寄存器数据向左位移一位(乘2)
A:我们举例子的CPU里面只有3个模块,就直接接了。真正的CPU里会有一个解码器(decoder),把指令翻译成需要的形式。Q:你举例子的简单CPU,如果我输入指令0011会怎么样?A:当然是同时激活了加法器和位移器从而产生不可预料的后果,简单的说因为你使用了没有设计的指令,所以后果自负呗。在真正的CPU上这么干大概率就是崩溃呗,不过肯定会有各种保护性的设计。 细心的小伙伴可能发现一个问题:你设计的指令【0001,数据与寄存器相加,结果保存到寄存器】这个一步做不出来吧? 毕竟还有一个回写的过程,实际上确实是这样。我们设计的简易CPU执行一个指令差不多得三步,读取指令,执行指令,写寄存器。 经典的RISC设计则是分5步:读取指令(IF),解码指令(ID),执行指令(EX),内存操作(MEM),写寄存器(WB)。我们平常用的x86的CPU有的指令可能要分将近20个步骤。 你可以理解有这么一个开关,我们啪的按一下,CPU就走一步,你按的越快CPU就走的越快。咦?听说你有个想法?少年,你这个想法很危险啊,姑且不说你能不能按那么快。拿现代的CPU来说,也就2GHz多吧,大概一秒也就按个20亿下吧。 就算你能按那么快,虽然速度是上去了,但功耗会大大增加,发热上升稳定性下降。江湖上确实有这种玩法,名曰超频,不过新手不推荐你尝试哈。 那CPU怎么知道自己走到哪一步了呢?前面不是介绍了FF么,这个不光可以用来存中间数据,也可以用来存中间状态,也就是走到哪了。 具体的设计涉及到FSM(finite-state machine),也就是有限状态机理论,以及怎么用FF实装。这个也是很重要的一块,考试必考哈,只不过跟题目关系不大,这里就不展开讲了。 我们再继续刚才的讲,现在我们有3个指令了。我们来试试算个(1+4)X2+3吧。







MOV 1
之后是4,+,那就加一下:
ADD 4
然后是2,*,那就乘一下(介于我们设计的乘法器暂时只能乘2,这个0是占位的):
SHL 0
最后是3,+,那再加一下:
ADD 3
最后我们把翻译好的汇编整理一下:
- 0100,数据读入寄存器A
- 0101,数据读入寄存器B (我们把汇编指令定义为MOVB)
- 0001,数据与寄存器A相加,结果保存到寄存器A
- 0011,数据与寄存器B相加,结果保存到寄存器B(我们把汇编指令定义为ADDB)
- 0010,寄存器A数据向左位移一位(乘2)
- 1100,把寄存器B的地址数据读入寄存器A(我们把汇编指令定义为RD)
- 1110,寄存器A的数据写到寄存器B指定的地址(我们把汇编指令定义为WR)
0101 1000 ; MOVB 16; 把栈底地址定义为1000
之后入栈的话,比如把数字3,4入栈:
