计算机中蕴藏的哲理

最基本的思想是:通过基本电路的接线,确立输入-输出规则,类似函数的入参和返回值,便构成一个功能电路单元。单元套单元组成新单元,如此往复。“一生二,二生三,三生万物”。这是硬件层面的。

软件层面的也是类似的道理。

向下不断的穷尽,我们会来到物理世界,最基本的电荷和磁场规则。再往里就是物理学还在探索的空间,未知。

向上不断的探索,我们会来到应用世界,充满了人类的欲望和需求。

一个领域依托于它的下一层,自己组织自己这一层级的基本单元之间的关系——本质就是排列组合的规则。

如果最基本的粒子是一,那么“一生二,二生三,三生万物”,物物相生相联,夫如是已。

本文的行文逻辑也是,从简入繁,由低向上,构建出一个“复杂”的CPU系统。虽是模拟,然代表了大致的脉络。

本文原始链接地址:https://blog.csdn.net/windanchaos/article/details/131524301

基本电路单元

参考:https://blog.csdn.net/windanchaos/article/details/81143641

主要是基本的电路单元

八位加法器

使用工具:https://www.logiccircuit.org/
工具中有基本的逻辑电路单元、输入输出、分线器、晶振模拟器、显示装置模拟单元等。

如下:半加器是异或、与门电路接线构成。2个输入2个输出。

  • 半加器 HA(HalfAdder)

  • 半加器组成个全加器 FA(FullAdder)

  • 8位的求反RE
  • 半加器组合成8位的计算器

寄存器

仍然是基本电路往更复杂电路组合的逻辑。

只不过,这部分电路有个特征,术语叫时序电路,其最基本的特征是相对组合电路来讲的,组合电路特定输入就得到特定输出,时序电路则不然,它的输出和输入的对应关系是不确定的,其电路的输出会接到输入上,最终输出是由输入、输出和电路当前状态决定。话不多说直接上截图。

  • R-S触发器,输出Q确定后,Set、Clear、Prs不改变,那么电路是Q值是稳定的,可存储一位二进制。

  • D触发器(R-S)组合起来,加了2个与门电路,具备控制是否可读可写的能力

  • D边沿触发器,增加了时钟上升沿才可以操作的电路

  • T触发器,D基础上接线,具备输出按时钟周期变化的能力,是计数器的基本单元

  • D边沿触发器组成一个能存储1byte(8个位)的单元

  • Byte单元增加各种控制输入,就组成1个8位寄存器

  • 3-8译码器,3个位(000),0和1变化有8种组合情况,特定组合选中特定的Byte单元,具有了寻址概念

  • 8x1电路,Ad是输入的3位地址

最后演示一下001号寄存器被选中后的,执行写入和读取的操作。开始是重置255和清零,之后演示从0到8修改寄存器中值。

加减法电路

利用已有的电路部件,搭建一个可以计算加法和减法的电路。此CPU计算单元雏形。

上面的MC、RAM、PC、Reg、ALU都有控制选中(CS片选)、可写(不可写则可读)的输入,选中时对应灯泡点亮示意。
使用16位中的13位二进制的01来对应。
通过不同的排列组合即可定义每个时钟周期电路的状态(哪些单元可以被操控读写)。

下面是对应电路的控制单元的标识,或运算一组和,就是控制电路了。

import os
# 指令相关
# ABC寄存器
A_WE = 1
A_CS = 1 << 1B_WE = 1 << 2
B_CS = 1 << 3C_WE = 1 << 4
C_CS = 1 << 5# 0为加,1为减
ALU_SUB = 1 << 6
ALU_EN = 1 << 7MC_CS = 1 << 8
MC_WE = 1 << 9PC_CS = 1 << 10
PC_WE = 1 << 11
PC_EN = 1 << 12
#空操作,未接线
NOTHING =  1 << 14
#停止(不再产生时钟信号)
HLT = 1 << 15dirname = os.path.dirname(__file__)
fileName = os.path.join(dirname,'ins.bin')micro = [
#启动电源PC=0
#空操作,用于清0,清0后PC=1
NOTHING,
# PC加1,从RAM中读取1下标的数到A寄存器,PC=2
MC_CS|A_CS|A_WE|PC_WE|PC_EN|PC_CS,
# PC加1,从RAM中读取2下标的数到B寄存器,PC=3
MC_CS|B_CS|B_WE|PC_WE|PC_EN|PC_CS,
# 读取A、B寄存器数到ALU单元并计算
ALU_EN|A_CS|B_CS,
#ALU计算结果输出到C寄存器
ALU_EN|C_CS|C_WE,
# PC=3,控制MC操控ROM可写,写入C寄存器读取的值
MC_CS|MC_WE|C_CS,
HLT
]
# 二进制指令输出到ins.bin文本,通过ciruit加载到ROM中。
with open(fileName,'wb') as file:for value in micro:file.write(value.to_bytes(2,byteorder='little'))print("finished compile")

以下是加法的gif演示(减法免了),演示从RAM中读取5和3到寄存器,使用ALU单元求和,输出到C寄存器,再写回到RAM。

组合CPU

给每个逻辑元件添加控制单元以达到,不同输入组合对应不同的输出。由于我们已实现了寄存器(一种能够记住1byte的单元),那么遍可以控制其允许输入/输出。

不同的原件,同一时刻的允许输入输出状态就定义了当时单元和单元之间的关系,如A寄存器输出,B是输入,其他不设置,那么此刻完成了A寄存器向B寄存器传输数据的目的。如此类推。

控制单元 Control Unit

控制单元是CPU的核心部件,由寄存器控制器、读写控制器及其他输入输入构成。如下:

控制单元接线——总览

将寄存器控制器和读写控制器接线,输入32位,对应位实现不同目的:

  • 低10位分2组,5+5分别标识写和读,接线到RWC上输入哪个单元读、哪个单元写。
  • 第11-15位分别标识源读、源写,目的读、目的写
  • 第16-19位位PC计数
  • 第20-23位为四则运算组合,一种8种
  • 第24-28 为控制ALU单元组合

PC 计数器

时钟下降沿(1->0)时完成指令计数,重新计数。是控制指令周期用的。

寄存器控制 RC

说明,W\R是5位输入,通过一个5-32译码器转换成0-32,可识别32个寄存器。

读写控制器RWC

读写控制器也是5位输入,接寄存器控制器

ALU

A、B是8位输入,OP是3位,3-8译码器,转为1-8,可支持8种运算。
1=加法 2=减法 3=加1 4=减1 5=And 6=OR 7=XOR 8=取反

内存控制器MC

RAM代表内存,MC为其控制单元

CPU接线

指令系统

执行的模式

通电之后,时钟定时脉动,提供给整个电路电压变化。通过control Uinit旁边的ROM中写入指令(32位的01组合数),CU(control Unit) 的PC每加1,则指令ROM读取的index +1,输入后从CU的d进入,完成对整个单元的控制。

  • 取指令:先从RAM中把指令取到IR寄存器,目的操作数取到DST中,原操作数取到SRC中。
  • 译指令,IR指令进入CU中,从L1输入,DST从L2输入,SRC从L3输入——拼出 控制信息 + 操作单元 的组合

最后对这些电路按设计转成代码,代码备注也由说明

管脚代码

# 寄存器,RAM=MC
MSR = 1
MAR = 2
MDR = 3
# RAM就是MC控制器
RAM = 4
IR = 5
DST = 6
SRC = 7
A = 8
B = 9
C = 10
D = 11
DI = 12
SI = 13
SP = 14
BP = 15
CS = 16
DS = 17
SS = 18
ES = 19
VEC = 20
T1 = 21
T2 = 22# 寄存器输出到总线上
MSR_OUT = MSR
MAR_OUT = MAR
MDR_OUT = MDR
RAM_OUT = RAM
IR_OUT = IR
DST_OUT = DST
SRC_OUT = SRC
A_OUT = A
B_OUT = B
C_OUT = C
D_OUT = D
DI_OUT = DI
SI_OUT = SI
SP_OUT = SP
BP_OUT = BP
CS_OUT = CS
DS_OUT = DS
SS_OUT = SS
ES_OUT = ES
VEC_OUT = VEC
T1_OUT = T1
T2_OUT = T2# 写入寄存器,暂时没搞懂为什么左移5位
_DST_SHIFT = 5
MSR_IN = MSR << _DST_SHIFT
MAR_IN = MAR << _DST_SHIFT
MDR_IN = MDR << _DST_SHIFT
RAM_IN = RAM << _DST_SHIFT
IR_IN = IR << _DST_SHIFT
DST_IN = DST << _DST_SHIFT
SRC_IN = SRC << _DST_SHIFT
A_IN = A << _DST_SHIFT
B_IN = B << _DST_SHIFT
C_IN = C << _DST_SHIFT
D_IN = D << _DST_SHIFT
DI_IN = DI << _DST_SHIFT
SI_IN = SI << _DST_SHIFT
SP_IN = SP << _DST_SHIFT
BP_IN = BP << _DST_SHIFT
CS_IN = CS << _DST_SHIFT
DS_IN = DS << _DST_SHIFT
SS_IN = SS << _DST_SHIFT
ES_IN = ES << _DST_SHIFT
VEC_IN = VEC << _DST_SHIFT
T1_IN = T1 << _DST_SHIFT
T2_IN = T2 << _DST_SHIFT# 电路中11-14位作为RWC单元的输入,控制S和D的读写,软件层面确认不同时读写同一个单元
# src中的值对应的寄存器,读取其值
SRC_R = 1 << 10
SRC_W = 1 << 11
DST_R = 1 << 12
DST_W = 1 << 13PC_CS = 1 << 14
PC_WE = 1 << 15
PC_EN = 1 << 16
PC_OUT = PC_CS
PC_IN = PC_CS | PC_WE | PC_EN
PC_INC = PC_CS | PC_WE# ALU
_OP_SHIFT = 17
OP_ADD = 0
OP_SUB = 1 << _OP_SHIFT
# 加减1
OP_INC = 2 << _OP_SHIFT
OP_DEC = 3 << _OP_SHIFT
OP_AND = 4 << _OP_SHIFT
OP_OR = 5 << _OP_SHIFT
OP_XOR = 6 << _OP_SHIFT
OP_NOT = 7 << _OP_SHIFT
ALU_OUT = 1 << 20
ALU_PSW = 1 << 21
ALU_INT_W = 1 << 22
ALU_INT = 1 << 23ALU_STI = ALU_INT_W
ALU_CLI = ALU_INT_W | ALU_INT# cyc标识当前指令执行完了,需要重置微程序的pc数
CYC = 1 << 30
HLT = 1 << 31# 二地址指令和一地址 指令
ADDR2 = 1 << 7
ADDR1 = 1 << 6
ADDR2_SHIFT = 4
ADDR1_SHIFT = 2# 四种寻址方式
AM_INS = 0  # 立即数
AM_REG = 1  # 寄存器
AM_DIR = 2  # 内存直接寻址
AM_RAM = 3  # 寄存器间接寻址

控制器代码controller.py

# 控制器import os
import assembly as ASM
import pindirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'micro.bin')
micro = [pin.HLT for _ in range(0x10000)]
# 跳转转移指令
CJMPS = {ASM.JO, ASM.JNO, ASM.JZ, ASM.JNZ, ASM.JP, ASM.JNP}def compile_addr2(addr, ir, psw, index):global micro# 操作op = ir & 0xf0amd = (ir >> 2) & 3  # 3 = 011ams = ir & 3INST = ASM.INSTRUCTIONS[2]if op not in INST:micro[addr] = pin.CYCreturnam = (amd, ams)if am not in INST[op]:micro[addr] = pin.CYCreturnEXEC = INST[op][am]if index < len(EXEC):micro[addr] = EXEC[index]else:micro[addr] = pin.CYCdef get_condition_jump(exec, op, psw):overflow = psw & 1zero = psw & 2parity = psw & 4if op == ASM.JO and overflow:return execif op == ASM.JNO and not overflow:return execif op == ASM.JZ and zero:return execif op == ASM.JNZ and not zero:return execif op == ASM.JP and parity:return execif op == ASM.JNP and not parity:return execreturn [pin.CYC]def get_interrupt(exec, op, psw):interrupt = psw & 8if interrupt:return execreturn [pin.CYC]def compile_addr1(addr, ir, psw, index):global microglobal CJMPSop = ir & 0xfcamd = ir & 3INST = ASM.INSTRUCTIONS[1]if op not in INST:micro[addr] = pin.CYCreturnif amd not in INST[op]:micro[addr] = pin.CYCreturnEXEC = INST[op][amd]if op in CJMPS:EXEC = get_condition_jump(EXEC, op, psw)if op == ASM.INT:EXEC = get_interrupt(EXEC, op, psw)if index < len(EXEC):micro[addr] = EXEC[index]else:micro[addr] = pin.CYCdef compile_addr0(addr, ir, psw, index):global micro# 操作op = irINST = ASM.INSTRUCTIONS[0]if op not in INST:micro[addr] = pin.CYCreturnEXEC = INST[op]if index < len(EXEC):micro[addr] = EXEC[index]else:micro[addr] = pin.CYC# 2^16次方是16进制的10000
# for循环对下标就行遍历赋值,ROM列有16个,一行一条指令。
# 16位组成:ir[8]+psw[4]+cyc[4],与运算高位和低位双截断
for addr in range(0x10000):ir = addr >> 8psw = (addr >> 4) & 0xfcyc = addr & 0xf# 小于取址长度,则写入取指令,6个时钟沿if cyc < len(ASM.FETCH):micro[addr] = ASM.FETCH[cyc]continueaddr2 = ir & (1 << 7)addr1 = ir & (1 << 6)# 取指令之后的indexindex = cyc - len(ASM.FETCH)if addr2:compile_addr2(addr, ir, psw, index)elif addr1:compile_addr1(addr, ir, psw, index)else:compile_addr0(addr, ir, psw, index)
with open(filename, 'wb') as file:for var in micro:value = var.to_bytes(4, byteorder='little')file.write(value)
print('micro instruction compile finished! ')

程序代码 compiler.py

主要完成汇编转机器码的工作

import os
import pin
import assembly as ASM
import redirname = os.path.dirname(__file__)
inputFileName = os.path.join(dirname, 'program.asm')
outputFileName = os.path.join(dirname, 'program.bin')# 代码的正则,分号是注释
annotation = re.compile(r"(.*?);.*")
# 代码
codes = []
# 标记,对应的代码
marks = {}
OP2 = {'MOV': ASM.MOV,'ADD': ASM.ADD,'CMP': ASM.CMP,'SUB': ASM.SUB,'AND': ASM.AND,'OR': ASM.OR,'XOR': ASM.XOR,
}
OP1 = {'INC': ASM.INC,'DEC': ASM.DEC,'NOT': ASM.NOT,'JMP': ASM.JMP,'JO': ASM.JO,'JNO': ASM.JNO,'JZ': ASM.JZ,'JNZ': ASM.JNZ,'JP': ASM.JP,'JNP': ASM.JNP,'PUSH': ASM.PUSH,'POP': ASM.POP,'CALL': ASM.CALL,'INT': ASM.INT,
}
OP0 = {'NOP': ASM.NOP,'HLT': ASM.HLT,'RET': ASM.RET,'STI': ASM.STI,'CLI': ASM.CLI,'IRET': ASM.IRET,
}OP2SET = set(OP2.values())
OP1SET = set(OP1.values())
OP0SET = set(OP0.values())# 可操作的寄存器
REGISTERS = {'A': pin.A,'B': pin.B,'C': pin.C,'D': pin.D,'SS': pin.SS,'CS': pin.CS,'SP': pin.SP,
}class Code(object):# 代码CODE = 1# 标记LABEL = 2def __init__(self, number, source: str, code_type=CODE):self.number = numberself.source = source.upper()self.op = Noneself.dst = Noneself.src = Noneself.code_type = code_type# 代码行self.index = 0self.prepare_source()def get_op(self):if self.op in OP2:return OP2[self.op]if self.op in OP1:return OP1[self.op]if self.op in OP0:return OP0[self.op]raise SyntaxError(self)# 获取操作数类型和其操作值def get_am(self, addr):global marksif not addr:return None, Noneif addr in marks:# 一行代码占3个字节return pin.AM_INS, marks[addr].index * 3if addr in REGISTERS:return pin.AM_REG, REGISTERS[addr]if re.match(r'^[0-9]+$', addr):return pin.AM_INS, int(addr)if re.match(r'^0X[0-9A-F]+$', addr):return pin.AM_INS, int(addr, 16)# 匹配直接寻址,内存单元取址送出10进制match = re.match(r'^\[([0-9]+)\]$', addr)if match:return pin.AM_DIR, int(match.group(1))# 匹配直接寻址,内存单元取址送出16进制match = re.match(r'^\[0X([0-9A-F]+)\]$', addr)if match:return pin.AM_DIR, int(match.group(1), 16)# 寄存器间接寻址,即将寄存器中的值作为ROM下标取出值送出match = re.match(r'^\[(.+)\]$', addr)if match and match.group(1) in REGISTERS:return pin.AM_RAM, REGISTERS[match.group(1)]raise SyntaxError(self)# 文本预处理,获取到指令-源操作数-目的操作数def prepare_source(self):if self.source.endswith(":"):self.type = self.LABELself.name = self.source.strip(':')return# 逗号分割,如果大于2就是错误tup = self.source.split(',')if len(tup) > 2:raise SyntaxError(self)if len(tup) == 2:self.src = tup[1].strip()# 将指令和操作数分开tup = re.split(r' +', tup[0])if len(tup) > 2:raise SyntaxError(self)elif len(tup) == 2:self.dst = tup[1].strip()self.op = tup[0].strip()# 计算指令-目的操作数-源操作数的二进制值def compile_code(self):op = self.get_op()amd, dst = self.get_am(self.dst)ams, src = self.get_am(self.src)if src is not None and (amd, ams) not in ASM.INSTRUCTIONS[2][op]:raise SyntaxError(self)if src is None and dst and amd not in ASM.INSTRUCTIONS[1][op]:raise SyntaxError(self)if src is None and dst is None and op not in ASM.INSTRUCTIONS[0]:raise SyntaxError(self)amd = amd or 0ams = ams or 0dst = dst or 0src = src or 0if op in OP2SET:ir = op | (amd << 2) | amselif op in OP1SET:ir = op | amdelse:ir = opreturn [ir, dst, src]def __repr__(self):return f'[{self.number}] - {self.source}'class SyntaxError(Exception):def __init__(self, code: Code, *args, **kwargs):super.__init__(*args, **kwargs)self.code = codedef compile_program():global codesglobal markswith open(inputFileName, encoding='utf8') as file:lines = file.readlines()# 遍历行for index, line in enumerate(lines):# 去掉空格符source = line.strip()# 去掉分号及后的备注,分号就是标识代码用的(简版),冒号是标识LAB的if ';' in source:match = annotation.match(source)source = match.group(1)code = Code(index + 1, source)codes.append(code)continueif source.endswith(":"):codes.append(Code(index + 2, source, Code.LABEL))continueif not source:continueresult = []current = None# 从后往前遍历代码行for var in range(len(codes) - 1, -1, -1):code = codes[var]if code.code_type == Code.CODE:current = coderesult.insert(0, code)continueif code.type == Code.LABEL:# 这里指向的是code的引用,后边的遍历改index不影响marks[code.name] = currentcontinueraise SyntaxError(code)# 更新索引indexfor index, var in enumerate(result):var.index = indexwith open(outputFileName, 'wb') as file:for code in result:values = code.compile_code()for value in values:if value is not None:result = value.to_bytes(1, byteorder='little')file.write(result)def main():try:compile_program()except SyntaxError as e:print(f'Syntax Error at {e.code}')print(f'program compile finished')if __name__ == '__main__':main()

汇编定义代码assembly.py

主要定义,不同指令的电路组合状态。电路组合状态从管脚中定义的基本电路控制单元,或运算得到。

import pin# 汇编# 取址
FETCH = [pin.PC_OUT | pin.MAR_IN,pin.RAM_OUT | pin.IR_IN | pin.PC_INC,pin.PC_OUT | pin.MAR_IN,pin.RAM_OUT | pin.DST_IN | pin.PC_INC,pin.PC_OUT | pin.MAR_IN,pin.RAM_OUT | pin.SRC_IN | pin.PC_INC,
]
# 指令定义
MOV = 0 | pin.ADDR2
ADD = (1 << pin.ADDR2_SHIFT) | pin.ADDR2
SUB = (2 << pin.ADDR2_SHIFT) | pin.ADDR2
CMP = (3 << pin.ADDR2_SHIFT) | pin.ADDR2
AND = (4 << pin.ADDR2_SHIFT) | pin.ADDR2
OR = (5 << pin.ADDR2_SHIFT) | pin.ADDR2
XOR = (6 << pin.ADDR2_SHIFT) | pin.ADDR2INC = (0 << pin.ADDR1_SHIFT) | pin.ADDR1
DEC = (1 << pin.ADDR1_SHIFT) | pin.ADDR1
NOT = (2 << pin.ADDR1_SHIFT) | pin.ADDR1
JMP = (3 << pin.ADDR1_SHIFT) | pin.ADDR1
# 条件转移
# 溢出和非溢出
JO = (4 << pin.ADDR1_SHIFT) | pin.ADDR1
JNO = (5 << pin.ADDR1_SHIFT) | pin.ADDR1
# 零和非0
JZ = (6 << pin.ADDR1_SHIFT) | pin.ADDR1
JNZ = (7 << pin.ADDR1_SHIFT) | pin.ADDR1
# 奇数和非奇数
JP = (8 << pin.ADDR1_SHIFT) | pin.ADDR1
JNP = (9 << pin.ADDR1_SHIFT) | pin.ADDR1
PUSH = (10 << pin.ADDR1_SHIFT) | pin.ADDR1
POP = (11 << pin.ADDR1_SHIFT) | pin.ADDR1
CALL = (12 << pin.ADDR1_SHIFT) | pin.ADDR1
INT = (13 << pin.ADDR1_SHIFT) | pin.ADDR1# SUB = (2 << pin.ADDR2_SHIFT) | pin.ADDR2
# SUB = (2 << pin.ADDR2_SHIFT) | pin.ADDR2
# SUB = (2 << pin.ADDR2_SHIFT) | pin.ADDR2
# 0操作数指令
# 啥也不干
NOP = 0
RET = 1
# 中断返回
IRET = 2
# 开中断
STI = 3
# 关中断
CLI = 4
# 停止
HLT = 0x3f  # 111111INSTRUCTIONS = {2: {MOV: {# 立即数寻址,将立即数放入SRC寄存器,存入DST种存放的具体寄存器(地址)中,这里只定义指令动作,具体执行之后解析(pin.AM_REG, pin.AM_INS): [pin.DST_W | pin.SRC_OUT,],(pin.AM_REG, pin.AM_REG): [pin.DST_W | pin.SRC_R,],(pin.AM_REG, pin.AM_DIR): [pin.SRC_OUT | pin.MAR_IN,pin.DST_W | pin.RAM_OUT,],(pin.AM_REG, pin.AM_RAM): [pin.SRC_R | pin.MAR_IN,pin.DST_W | pin.RAM_OUT,],(pin.AM_DIR, pin.AM_INS): [pin.DST_OUT | pin.MAR_IN,pin.RAM_IN | pin.SRC_OUT,],(pin.AM_DIR, pin.AM_DIR): [pin.SRC_OUT | pin.MAR_IN,pin.RAM_OUT | pin.T1_IN,pin.DST_OUT | pin.MAR_IN,pin.RAM_IN | pin.T1_OUT,],(pin.AM_DIR, pin.AM_RAM): [pin.SRC_R | pin.MAR_IN,pin.RAM_OUT | pin.T1_IN,pin.DST_OUT | pin.MAR_IN,pin.RAM_IN | pin.T1_OUT,],(pin.AM_RAM, pin.AM_INS): [pin.DST_R | pin.MAR_IN,pin.RAM_IN | pin.SRC_OUT,],(pin.AM_RAM, pin.AM_REG): [pin.DST_R | pin.MAR_IN,pin.RAM_IN | pin.SRC_R,],(pin.AM_RAM, pin.AM_DIR): [pin.SRC_OUT | pin.MAR_IN,pin.RAM_OUT | pin.T1_IN,pin.DST_R | pin.MAR_IN,pin.RAM_IN | pin.T1_OUT,],(pin.AM_RAM, pin.AM_RAM): [pin.SRC_R | pin.MAR_IN,pin.RAM_OUT | pin.T1_IN,pin.DST_R | pin.MAR_IN,pin.RAM_IN | pin.T1_OUT,],},ADD: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_ADD | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW,],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_ADD | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW,],},CMP: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_SUB | pin.ALU_PSW,],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_SUB | pin.ALU_PSW,],},SUB: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_SUB | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_SUB | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],},AND: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_AND | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_AND | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],},OR: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_OR | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_OR | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],},XOR: {(pin.AM_REG, pin.AM_INS): [pin.DST_R | pin.A_IN,pin.SRC_OUT | pin.B_IN,pin.OP_XOR | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],(pin.AM_REG, pin.AM_REG): [pin.DST_R | pin.A_IN,pin.SRC_R | pin.B_IN,pin.OP_XOR | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],},},1: {INC: {pin.AM_REG: [pin.DST_R | pin.A_IN,pin.OP_INC | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW],},DEC: {pin.AM_REG: [pin.DST_R | pin.A_IN,pin.OP_DEC | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW,],},NOT: {pin.AM_REG: [pin.DST_R | pin.A_IN,pin.OP_NOT | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW,],},JMP: {# 立即数写入到PCpin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JO: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JNO: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JZ: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JNZ: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JP: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},JNP: {pin.AM_INS: [pin.DST_OUT | pin.PC_IN],},PUSH: {pin.AM_INS: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 读取目的寄存器的值到RAM,地址由MSR+MARpin.DST_OUT | pin.RAM_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],pin.AM_REG: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 读取目的寄存器的值到RAM,地址由MSR+MARpin.DST_R | pin.RAM_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],},POP: {pin.AM_REG: [# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,pin.SP_OUT | pin.MAR_IN,# RAM读取值到目的寄存器,地址由MSR+MARpin.DST_W | pin.RAM_OUT,pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_INC,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],},CALL: {pin.AM_INS: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 保存当前pc到RAMpin.PC_OUT | pin.RAM_IN,# 读取目的寄存器的值PCpin.DST_OUT | pin.PC_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],pin.AM_REG: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 保存当前pc到RAMpin.PC_OUT | pin.RAM_IN,# 读取目的寄存器的值PCpin.DST_R | pin.PC_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],},INT: {pin.AM_INS: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 保存当前pc到RAMpin.PC_OUT | pin.RAM_IN,# 读取目的寄存器的值PCpin.DST_OUT | pin.PC_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN | pin.ALU_PSW | pin.ALU_CLI,],pin.AM_REG: [# 栈顶指针减一获取栈地址pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_DEC,pin.SP_OUT | pin.MAR_IN,# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,# 保存当前pc到RAMpin.PC_OUT | pin.RAM_IN,# 读取目的寄存器的值PCpin.DST_R | pin.PC_IN,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN | pin.ALU_PSW | pin.ALU_CLI,],},},0: {NOP: [pin.CYC],HLT: [pin.HLT],RET: [# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,pin.SP_OUT | pin.MAR_IN,# RAM读取值写回PC计数器pin.PC_IN | pin.RAM_OUT,pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_INC,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN,],IRET: [# 栈段地址送到MSR寄存器pin.SS_OUT | pin.MSR_IN,pin.SP_OUT | pin.MAR_IN,# RAM读取值写回PC计数器pin.PC_IN | pin.RAM_OUT,pin.SP_OUT | pin.A_IN,pin.SP_IN | pin.ALU_OUT | pin.OP_INC,# 恢复MSR到代码段pin.CS_OUT | pin.MSR_IN | pin.ALU_PSW | pin.ALU_STI,],STI: [pin.ALU_PSW | pin.ALU_STI,],CLI: [pin.ALU_PSW | pin.ALU_CLI,],}
}

实现的指令

二地址指令

  • MOV
  • ADD
  • CMP
  • SUB
  • AND
  • OR
  • XOR

一地址指令

  • INC
  • DEC
  • NOT
  • JMP 跳转
  • JO 溢出跳转
  • JNO 非溢出跳转
  • JZ 零转
  • JNZ
  • JP 奇偶
  • JNP
  • PUSH
  • POP
  • CALL
  • INT中断(内部的)

零地址指令

  • NOP
  • HLT
  • RET call对应恢复
  • IRET 中断恢复
  • STI start中断
  • CLI close中断

演示

下面演示汇编代码的执行。

MOV D,3;
MOV C,4;
ADD D,C;
HLT;

该代码先被汇编解析代码编译到program.bin的二进制文件中,加载CPU的RAM,作为程序源。
然后控制器代码生成的二进制文件加载到CPU的ROM中,作为指令源。
最后,加法的输出结果是一个是7,在ALU旁输出和D寄存器中都是。。。

尾声

有了能支持汇编代码的基础,在此基础上,我们能够持续向上“生万物”,这是一条辉煌而又艰辛的道路。

使用模拟电路制造CPU——从硬件到软件的设计相关推荐

  1. 硬件模拟大师_科普丨硬件检测软件3D Mark究竟多“硬核”?

    随着硬件更新换代和兼容性增强,笔记本电脑的综合性能甄别变得愈发复杂,如何精准评判一款电脑性能对众多电脑小白来说显得至关重要.尽管鲁大师同样可以提供简约直观的跑分但其偏向系统优化,高性能硬件测试更多只能 ...

  2. 模拟电路--一种简单的无源限幅电路的设计

    一种简单的无源限幅电路的设计 设计需求 设计方案 仿真结果 设计需求 有很多地方需要对输入端或者输出端的信号进行限幅.最近在做的一个电路对输入端有比较严格的信号幅度限制,所以需要在电路的输入端加上一个 ...

  3. [模拟电路]ADI放大器笔记 - 差分放大器单端输入电阻设计

    对于平平衡(差分)输入的差分放大器配置衡差分输入信号,两个输入端(+DIN和-DIN)之间的输入阻抗(RIN,dm)可简单计算为    对于非平衡单端输入信号(见图2),通过公式来计算输入阻抗: 该电 ...

  4. 单片机:ADC模数转换实验(内含ADC介绍+XPT2046芯片介绍+硬件电路设计+软件编程设计+原始代码)

     ADC简介 单片机只能分析数字信号,帮你分析模拟信号.所以接受外界模拟量--->数字量(0或1) 分辨率:模拟信号能输出离散信号的个数.通常用2进制存储,所以通常用bit.输入5V,最小的电压 ...

  5. 【转载】关于模拟电路的学习历程

    复旦攻读微电子专业模拟芯片设计方向研究生开始到现在五年工作经验,已经整整八年了,其间聆听过很多国内外专家的指点.最近,应朋友之邀,写一点心得体会和大家共享.我记得本科刚毕业时,由于本人打算研究传感器的 ...

  6. 硬件工程师面试集锦 模拟电路 数字电路 IC设计基础 单片机 信号与系统 DSP 嵌入式

    模拟电路   1.基尔霍夫定理的内容是什么?(仕兰微电子)   2.平板电容公式(C=εS/4πkd).(未知)   3.最基本的如三极管曲线特性.(未知)   4.描述反馈电路的概念,列举他们的应用 ...

  7. (转)硬件工程师面试集锦 模拟电路 数字电路 IC设计基础 单片机 信号与系统 DSP 嵌入式

    模拟电路  1.基尔霍夫定理的内容是什么?(仕兰微电子)  2.平板电容公式(C=εS/4πkd).(未知)  3.最基本的如三极管曲线特性.(未知)  4.描述反馈电路的概念,列举他们的应用.(仕兰 ...

  8. 硬件基础——模拟电路

    硬件基础--模拟电路 模拟电路 何为模拟? 电子管(真空电子管) 电子二极管 电子三极管 半导体 本征半导体 N型半导体 P型半导体 PN结 晶体管 晶体二极管 晶体三极管 MOS场效应管 本篇为模拟 ...

  9. 硬件基础知识(13)---模拟电路中大量使用的滤波和隔直LC网络的值计算

    电容最重要的特性就是直流无法通过,交流可以通过."隔直"是电容最正统的用法之一.例如图示中的差分模拟麦克风电路,麦克风可以理解为一个1.5kR左右的电阻,麦克风的两端的输出,可以理 ...

最新文章

  1. 哈哈,我的博客开通啦,欢迎光临~~~~~~~~~~~~
  2. 发送文件到打印机,打印机收不到(无线打印机)
  3. 藏青色在html页面怎么写,Html页面支持暗黑模式的实现
  4. AI 质检学习报告——学习篇——AI质检产生背景和发展过程
  5. 二、Zabbix-zabbix server部署-LNMP
  6. php 调用openoffice,PHP调用OpenOffice实现word转PDF的方法
  7. 2.6 谷歌 Inception 网络简介
  8. FreeSwitch通过远程接口验证用户登录
  9. 安装增强功能时,未能加载虚拟光盘 D:\VirtualBox\VBoxGuestAdditions.iso到虚拟电脑
  10. Excel线性回归分析
  11. 简述 Erasure Code,EC 纠删码原理
  12. 小米手机计算机usb连接,小米5手机怎么连接电脑 USB调试方法教程
  13. Linux-bash笔记
  14. 使用JavaScript实现动态效果
  15. Samba服务器的配置全过程
  16. 【学习笔记 31】 buu [0CTF 2016]piapiapia
  17. 面向未来,镭速助力企业构建文件安全外发新生态
  18. 灰狼算法(GWO)优化支持向量机的数据回归预测,GWO-SVM回归预测,多输入单输出模型。
  19. 苹果手机互传一键换机
  20. 编程之法-C语言应用开发与工程实践-C语言概述

热门文章

  1. eclipse使用版本控制工具CVN
  2. HTML5汉堡包西餐美食网站模板
  3. UnicodeEncodeError: 'latin-1' codec can't encode character '\u7537' in position 184: ordinal not in
  4. matlab与机器学习(三)以辛烷值含量预测为例BP神经网络(含代码解析)
  5. windows11 如何关闭防火墙
  6. 重磅发布 | Serverless 应用中心:Serverless 应用全生命周期管理平台
  7. ISO20000认证程序阶段
  8. 2023年全国最新安全员精选真题及答案47
  9. win10+python3.7环境下安装pydensecrf(实测有效!)
  10. Python如何将字符串分割成单个字符,并形成一个list?