#模拟 CPU 执行完整程序代码的全部过程
#初始化主存、通用寄存器、指令寄存器和程序计数器
mem = ['']*1000 #主存
reg = [0]*10 #通用寄存器
pReg = 0 #程序计数器
iReg = '' #指令寄存器
#程序加载:从主存mem的address地址开始存放file文件
def loadProgram(file, mem, address):
########## Begin ##########
txt = open(file, 'r')
a = txt.readlines()
for x in a:
x = x.split()
x = " ".join(x[1:])
mem[address] = x
address += 1
########## End ##########
#取指令:根据程序计数器给出的地址取出主存对应的指令放入指令寄存器
def fetch(mem, pReg):
########## Begin ##########
iReg = mem[pReg]
pReg += 1
########## End ##########
return pReg, iReg
#指令译码:解析指令寄存器中的指令,不存在的操作数置为None
def decode(iReg):
########## Begin ##########
a = iReg.split()
for i in range(1,len(a)):
a[i] = int(a[i])
while len(a) != 3:
a.append(None)
opcode = a[0]
op1 = a[1]
op2 = a[2]
########## End ##########
return opcode,op1,op2 #opcode为操作码,op1为第一个操作数,op2为第二个操作数
#执行和写结果:根据指令解析的操作码执行对应的操作,若为停机指令返回 False,其余指令返回 True
##opcode为操作码,op1为第一个操作数,op2为第二个操作数
#reg为通用寄存器,mem为主存,address为程序第一条指令在主存中的地址
def execute(opcode, op1, op2, reg, mem, address):
global pReg
########## Begin ##########
if opcode == "add":
reg[op1] = reg[op1] + reg[op2]
elif opcode == "sub":
reg[op1] = reg[op1] - reg[op2]
elif opcode == "mul":
reg[op1] = reg[op1] * reg[op2]
elif opcode == "div":
reg[op1] = reg[op1] // reg[op2]
elif opcode == "mov1":
reg[op1] = mem[op2]
elif opcode == "mov3":
reg[op1] = op2
elif opcode == "in":
reg[op1] = eval(input())
elif opcode == "out":
print(reg[op1])
elif opcode == "jmp":
pReg = op1 + address
elif opcode == "jz":
if reg[op1] == 0:
pReg = op2 + address
elif opcode == "mov2":
mem[op1] = reg[op2]
else:
return False
return True
########## End ##########
#完整过程模拟:程序加载、取指令、指令译码、指令执行和写结果
def run(file, addr):
global pReg, iReg
########BEGIN########
pReg = addr
loadProgram(file, mem, addr)
while True:
pReg, iReg = fetch(mem, pReg)
opcode,op1,op2 = decode(iReg)
if not execute(opcode, op1, op2, reg, mem, address):
break
########## End ##########
file = input() #获取TOY程序代码存放的文件名字
address = int(input()) #获取TOY程序第一条代码加载到的主存物理地址
run(file, address) #加载TOY程序到主存指定地址,并执行