【csapp实验4】Y86-64指令模拟器

一、题目要求

使用Python/C/C++语言实现一个Y86-64模拟器(可参考附件实现),要求: 1)能够从文件中读取Y86-64机器码(Xilinx coe文件格式) 2)能够解释执行Y86-64指令 3)能够将存储器/寄存器值输出

提示:可采用多周期、流水线实现 使用Xilinx coe格式输入文件(参考:Xilinx COE文件生成_xilinx coe-CSDN博客)

测试: 使用Y86-64指令实现从1加到100,并将结果保存到存储器中

ps: 说实话这个实验比较简单,没有什么太大的自由发挥时间,python相较于C语言会更好写一点   不过多周期流水线???我没想出来怎么写

二、代码开源(就当是学姐给你们的馈赠了哈哈哈哈哈哈哈哈)

import sys
class InstructionType:
    halt = '00'
    nop = '10'
    rrmovq = '20'
    cmovle = '21'
    cmovl = '22'
    cmove = '23'
    cmovne = '24'
    cmovge = '25'
    cmovg = '26'
    irmovq = '30'
    rmmovq = '40'
    mrmovq = '50'
    addq = '60'
    subq = '61'
    andq = '62'
    xorq = '63'
    jmp = '70'
    jle = '71'
    jl = '72'
    je = '73'
    jne = '74'
    jge = '75'
    jg = '76'
    call = '80'
    ret = '90'
    pushq = 'A0'
    popq = 'B0'
Y86=InstructionType()
mem = [0]*10010    #指令存储器
reg = [0]*16    #15个常用寄存器
iReg = ''    #当前指令
pReg = 0    #PC
ZF = 0   #零
SF = 0   #符号
OF = 0   #溢出
reg[4] = 10000  #%rsp栈指针
def loadProgram(file): #把文件地址和指令读入存储器中
    global mem, reg, iReg, pReg,ZF,OF,SF #声明全局变量
    fil = open(file,'r') #读文件
    first = True #现在是不是第一行
    lineno = 0 #行数
    while True:
        line = fil.readline()  #读一行
        line=line.rstrip('\n')
        line = line.rstrip(',')
        line =line.rstrip(';')
        lineno += 1 #行数
        if line == '': 
            break #读完就退出
        fids = line.split() #以词为数组
        try:
            address = int(fids[0],16)   #地址 读入第1个词,默认16进制
            instruc = fids[1]   #指令
            if first:
                pReg = address    #开头
                first = False
            mem[address] = instruc 
        except:
            if (lineno>2):
              print(f'File {file} line {lineno} has error') #提供信息报错!!!
            pass
    fil.close
def imm(str): #处理立即数 "把小端正过来"
    n = len(str)
    s =''
    for i in range(n-2,-1,-2):
        s = s+str[i:i+2]
    return s

Count = 1 #???

def cycle():
    global mem, reg, iReg, pReg,OF,ZF,SF,Count #声明全局变量

    iReg = str(mem[pReg])   #当前指令
    pReg = len(iReg)//2 + pReg   #PC+1
    opcode = iReg[0:2]
    if opcode == Y86.halt:
        return False #终止运行
    elif opcode == Y86.nop:
        return True #空操作
    elif opcode == Y86.rrmovq: 
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        reg[rB] = reg[rA]
    elif opcode == Y86.cmovle: 
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if ZF or SF:
            reg[rB] = reg[rA]                  
    elif opcode == Y86.cmovl: 
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if SF:
            reg[rB] = reg[rA]          
    elif opcode == Y86.cmove:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if ZF:
            reg[rB] = reg[rA]  
    elif opcode == Y86.cmovne:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if not ZF:
            reg[rB] = reg[rA]  
    elif opcode == Y86.cmovge:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if ZF or (not SF):
            reg[rB] = reg[rA]  
    elif opcode == Y86.cmovg:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        if not SF:
            reg[rB] = reg[rA]  
    elif opcode == Y86.irmovq:
        rB = int(iReg[3],16)
        imm0 = int(imm(iReg[4:]),16)
        reg[rB] = imm0
    elif opcode == Y86.rmmovq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)     
        imm1 =  int(imm(iReg[4:]),16)
        mem[reg[rB]+imm1] = reg[rA]         
    elif opcode == Y86.mrmovq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)     
        imm2 =  int(imm(iReg[4:]),16)
        reg[rA] = mem[reg[rB]+imm2]           
    elif opcode == Y86.addq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        flag = 0
        if reg[rA]>0 and reg[rB]>0: flag=1
        if reg[rA]<0 and reg[rB]<0: flag=2
        reg[rB] = reg[rA]+reg[rB]
        if reg[rB]==0: 
            ZF=1
        else: ZF=0
        if reg[rB]<0: 
            SF=1
        else: SF=0       
        if (flag==1 and reg[rB]<0) or (flag==2 and reg[rB]>0): 
            OF=1
        else: OF=0               
    elif opcode == Y86.subq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        flag = 0
        if reg[rA]>0 and reg[rB]>0: flag=1
        if reg[rA]<0 and reg[rB]<0: flag=2
        reg[rB] = reg[rB]-reg[rA]  
        if reg[rB]==0: 
            ZF=1
        else: 
            ZF=0
        if reg[rB]<0: 
            SF=1
        else: SF=0       
        if (flag==1 and reg[rB]<0) or (flag==2 and reg[rB]>0): 
            OF=1
        else: OF=0        
    elif opcode == Y86.andq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        reg[rB] = reg[rA]&reg[rB]
        if reg[rB]==0: 
            ZF=1
        else: 
            ZF=0
        if reg[rB]<0: SF=1
        else: SF=0       
        OF=0    
    elif opcode == Y86.xorq:
        rA = int(iReg[2],16)
        rB = int(iReg[3],16)
        reg[rB] = reg[rA]^reg[rB] 
        if reg[rB]==0: 
            ZF=1
        else: 
            ZF=0
        if reg[rB]<0: SF=1
        else: SF=0        
        OF=0 
    elif opcode == Y86.jmp:
        pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.jle:
        if ZF or SF:
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.jl:
        if SF:
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.je:
        if ZF:
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.jne:
        if not ZF:
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.jge:
        if ZF or (not SF):
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.jg:
        if not SF:
            pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.call:
        mem[reg[4]-8] = pReg
        reg[4] = reg[4]-8
        pReg = int(imm(iReg[2:]),16)
    elif opcode == Y86.ret:
        pReg = mem[reg[4]]
        reg[4] = reg[4]+8
    elif opcode == Y86.pushq:
        rA = int(iReg[2],16)
        mem[reg[4]-8] = reg[rA]
        reg[4] = reg[4] - 8
    elif opcode == Y86.popq:
        rA = int(iReg[2],16)
        reg[rA] = mem[reg[4]]
        reg[4] = reg[4]+8
    else:
        print(f'Unknow opcode {opcode}')
    return True

def run(file): #运行程序
    global mem, reg, iReg, pReg,OF,SF,ZF

    loadProgram(file)

    while True:
        if not cycle():
            break

path0='Y86-64jiqi.coe'
run(path0)
print(f'寄存器的值:{reg[0]}')
print(f'%rax的值放到地址为100处,即0x64处的存储器的值:{mem[100]}')

三、读入coe文件

MEMORY_INITIALIZATION_RADIX=16;
MEMORY_INITIALIZATION_VECTOR=
000 6300,
002 6333,
004 30F80100000000000000,
00E 30F96400000000000000,
018 6083,
01A 6030,
01C 2032,
01E 6192,
020 741800000000000000,
029 40090000000000000000,
033 00;

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值