图一 TOY计算机的结构


  如图 1 所示,TOY 计算机的核心硬件装置主要包括主存和 CPU。

  TOY 主存用来存储正在执行的 TOY 程序和相关数据, TOY 的主存共包含 1000 个主存单元,主存单元的地址依次为 000 ~ 999,每个主存单元可以存储一条 TOY 指令或一个相关数据。
  TOY 的 CPU 是用来执行 TOY 指令的,每次执行一条指令。在 CPU 中,通用寄存器是用来存储临时数据的,如执行完 mov3 1 12mov3 2 13 两条指令后,第 1 号和第 2 号寄存器中的值分别为 12 和 13,这两个数据会在后面的指令中被用到,TOY 计算机中共有 10 个通用寄存器,编号从 0 到 9;指令寄存器中存储了正在被执行的指令,如图 1 中,正在被 CPU 执行的指令是 add 1 2 指令;程序计数器用来存储下一条指令的地址,如图 1 中,程序计数器的值为 003,表示下一条被执行的指令是第 003 号主存单元中的指令

图二 TOY程序示例

加载 TOY 程序是指把 TOY 程序从外存载入到 TOY 的主存,从而使 CPU 可以执行程序中的各指令,其实就是把 .toy 文件中的程序指令放入到对应的主存单元(即列表 mem 中的对应位置),如果没有特意说明,就表示从主存地址 000 对应的单元开始连续存放。例如,若将图 1 中 add.toy 文件加载到主存,则 add.toy 文件第 3 行002 add 1 2中的指令add 1 2将被放入主存第 002 号单元,也就是将列表 mem 中下标为 2 的元素赋值为add 1 2

CPU 的功能是依次执行程序中的各条指令,在执行一条指令时其工作过程如下:

  • 取指令:按照程序计数器的值,取出对应主存单元中的指令,存入指令寄存器,并将程序计数器的值加 1,以便下个指令周期取出的是下一条指令;
  • 译码:对指令寄存器中的指令进行分析,取出操作码和各操作数;
  • 执行和写结果:根据操作码对操作数进行处理,并将处理结果放入指令指定的地方。

表1 TOY计算机的指令集

表2 TOY计算机的扩展指令

 python模拟拓展TOY计算机指令集工作过程

#初始化主存mem、通用寄存器reg、程序计数器pReg、指令寄存器iReg、状态寄存器CF
def init():
    global mem,reg,pReg,iReg,CF
    mem = ['']*1000     #主存
    reg = [0]*10       #通用寄存器
    pReg = 0          #程序计数器
    iReg = ''         #指令寄存器
    CF = 0
    
#程序加载:从主存mem的address地址开始存放file文件
def loadProgram(file,  mem, address):
    ########## Begin ##########
    txt = open(file, 'r')
    s = txt.readlines()
    for x in s :
        l = len(x)
        bg, L = 0, []
        while bg < l :
            mdl = ''
            while bg < l and x[bg] != ' ' and x[bg] != '\t' :
                mdl = mdl + x[bg]
                bg += 1
            while bg < l and (x[bg] == ' ' or x[bg] == '\t'):
                bg += 1
            L.append(mdl)
        L.pop(0)
        mem[address] = ' '.join(L)
        address = address + 1

    
#取指令:根据程序计数器给出的地址取出主存对应的指令放入指令寄存器
def fetch():
    global mem, pReg, iReg
    iReg = mem[pReg]
    return pReg, iReg

    
#指令译码:解析指令寄存器中的指令,不存在的操作数置为None
def decode():
    global iReg
    ########## Begin ##########
    l = len(iReg)
    cnt, i = 0, 0
    L = []
    while i < l :
        while i < l and iReg[i] == ' ' :
            i = i + 1
        if i == l :
            break
        cnt = cnt + 1; mdl = ''
        while i < l and iReg[i] != ' ' :
            mdl = mdl + iReg[i]
            i = i + 1
        if cnt > 1 :
            bg = 0
            while bg < len(mdl) and mdl[bg] == '0' :
                bg = bg + 1
            mdl = mdl[bg : ]
        L.append(mdl)
    tmp = cnt
    while cnt < 3 :
        L.append('None')
        cnt = cnt + 1
    if tmp == 1 :
        return L[0], 0, 0
    elif tmp == 2 :
        if L[1] == '' or L[1] == '\n':
            return L[0], 0, 0
        return L[0], eval(L[1]), 0
    else :
        ret1, ret2 = 0, 0
        if L[1] != '' and L[1] != '\n':
            ret1 = eval(L[1])
        if L[2] != '' and L[2] != '\n':
            ret2 = eval(L[2])
        return L[0], ret1, ret2
    

#执行和写结果:根据指令解析的操作码执行对应的操作,若为停机指令返回 False,其余指令返回 True
##opcode为操作码,op1为第一个操作数,op2为第二个操作数
def execute(opcode,op1,op2, address):
    global reg, pReg, CF, mem
    ########## Begin ##########
    global reg, pReg, CF, mem
    flag = False
    if opcode == 'mov1' :
        reg[op1] = eval(mem[op2])
    elif opcode == 'mov2' :
        mem[op1] = str(reg[op2])
    elif opcode == 'mov3' :
        reg[op1] = op2
    elif opcode == 'add' :
        reg[op1] += reg[op2]
    elif opcode == 'sub' :
        reg[op1] -= reg[op2]
    elif opcode == 'mul' :
        reg[op1] *= reg[op2]
    elif opcode == 'div' :
        reg[op1] = reg[op1] // reg[op2]
    elif opcode == 'jmp' :
        iReg = mem[op1]
        pReg = op1 + address
        flag = True
    elif opcode == 'jz' :
        if reg[op1] == 0 :
            flag = True
            iReg = mem[op2]
            pReg = op2 + address
    elif opcode == 'in' :
        reg[op1] = eval(input())
    elif opcode == 'out' :
        print(reg[op1])
    elif opcode == 'add2' :
        reg[op1] += op2
    elif opcode == 'cmp' :
        if reg[op1] <= op2 :
            CF = 1
        else :
            CF = 0
    elif opcode == 'ble' :
        if CF :
            pReg = reg[op1] + address
            flag = True
    if flag == False :
        pReg = pReg + 1
    if opcode != 'halt' and opcode != 'halt\n':
        result = True
    else :
        result = False
    return result


#完整过程模拟:程序加载、取指令、指令译码、指令执行和写结果
def run(file, addr):
    global pReg, iReg, reg
    ######## Begin ########
    pReg = addr
    loadProgram(file, mem, addr)
    while True :
        pReg, iReg = fetch()
        L, op1, op2 = decode()
        mdl = execute(L, op1, op2, addr)
        if mdl == False :
            break

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐