Files
csapp2025/y86lab/Y86_toy.py
2025-04-12 10:18:45 +08:00

269 lines
6.2 KiB
Python
Executable File

#encoding=utf-8
# reg file
reg = {
'rax':0,
'rcx':0,
'rdx':0,
'rbx':0,
'rsp':0,
'rbp':0,
'rsi':0,
'rdi':0,
'r8' :0,
'r9' :0,
'r10':0,
'r11':0,
'r12':0,
'r13':0,
'r14':0,
}
# 读取可执行文件
def read_exe_file(path):
infile = open(path)
file = infile.readlines()[2:]
return file
# 名称转换
def get_reg(s):
s = s.upper()
reg_name = {
'0':'rax',
'1':'rcx',
'2':'rdx',
'3':'rbx',
'4':'rsp',
'5':'rbp',
'6':'rsi',
'7':'rdi',
'8':'r8' ,
'9':'r9' ,
'A':'r10',
'B':'r11',
'C':'r12',
'D':'r13',
'E':'r14',
'F':None
}
return reg_name[s]
# 小端数据处理
def data_reverse(data):
return int(''.join([data[i:i+2] for i in range(16,-2,-2)]),16)
# 标志处理
def flags(result):
global zf,sf,of
if result == 0:
zf = 1
else:
zf = 0
if result < 0:
sf = 1
else:
sf = 0
if result > 4294967296 or result < -4294967296: #溢出
of = 1
else:
of = 0
# 标志位
zf = 0
sf = 0
of = 0
pc = 0
stat = 0
mem = [0 for i in range(101)]
reg['rsp'] = 100
try:
exe_file = read_exe_file("./Y86_instr.coe")
if len(exe_file) < 1:
exit()
except FileNotFoundError:
print(f"FileNotFoundError: {"./Y86_instr.coe"} not found, the progarm will use internal exe_file stored in this python code")
#exe_file:
#0 irmovq $1,%rax 30f001000000
#1 irmovq $1,%r8 30f801000000
#2 irmovq $0,%rbx 30f300000000
#3 irmovq $100,%rdx 30f264000000
#loop:
#4 subq %rax,%rdx 6102
#5 jl then 720a000000
#6 irmovq $100,%rdx 30f264000000
#7 addq %rax,%rbx 6003
#8 addq %r8,%rax 6080
#9 jmp loop 7004000000
#then:
#10 rmmovq %rbx,0(%rsp) 403400000000
exe_file = ['30f001000000',
'30f801000000',
'30f300000000',
'30f264000000',
'6102',
'720a000000',
'30f264000000',
'6003',
'6080',
'7004000000',
'403400000000',
]
# 主循环
def cycle():
global pc
s = exe_file[pc]
ins = s[0]
fn = s[1]
if ins == '0': # halt
print("instr \'halt\' is not allowed to be used by application")
return False
elif ins == '1': # nop
pc += 1
elif ins == '2': # mov
ra = get_reg(s[2])
rb = get_reg(s[3])
if fn == '0': # rrmovq
reg[rb] = reg[ra]
elif fn == '1': # cmovle
if (sf ^ of) | zf:
reg[rb] = reg[ra]
elif fn == '2': # cmovl
if sf ^ of:
reg[rb] = reg[ra]
elif fn == '3': # cmove
if zf:
reg[rb] = reg[ra]
elif fn == '4': #cmovne
if ~zf:
reg[rb] = reg[ra]
elif fn == '5': #cmovge
if ~(sf ^ of):
reg[rb] = reg[ra]
elif fn == '6': #cmovg
if ~(sf ^ of) & ~ zf:
reg[rb] = reg[ra]
pc += 1
elif ins == '3': # irmovq
ra = None
rb = get_reg(s[3])
data = data_reverse(s[4:])
reg[rb] = data
pc += 1
elif ins == '4': # rmmovq
ra = get_reg(s[2])
rb = get_reg(s[3])
data = reg[ra]
mem[reg[rb]] = data
pc += 1
elif ins == '5': # mrmovq
ra = get_reg(s[2])
rb = get_reg(s[3])
data = mem[reg[rb]]
reg[ra] = data
pc += 1
elif ins == '6': # OPq
ra = get_reg(s[2])
rb = get_reg(s[3])
if fn == '0':
reg[rb] = reg[rb] + reg[ra]
elif fn == '1':
reg[rb] = reg[rb] - reg[ra]
elif fn == '2':
reg[rb] = reg[rb] & reg[ra]
elif fn == '3':
reg[rb] = reg[rb] ^ reg[ra]
flags(reg[rb])
pc += 1
elif ins == '7': #jXX
dst = data_reverse(s[2:])
if fn =='0': # jmp
pc = dst
elif fn =='1': #jle
if (sf ^ of) | zf:
pc = dst
else:
pc += 1
elif fn =='2': #jl
if sf ^ of:
pc = dst
else:
pc += 1
elif fn =='3': #je
if zf:
pc = dst
else:
pc += 1
elif fn =='4': #jne
if ~zf:
pc = dst
else:
pc += 1
elif fn =='5': #jge
if ~(sf ^ of):
pc = dst
else:
pc += 1
elif fn =='6': #jg
if ~(sf ^ of) & ~ zf:
pc = dst
else:
pc += 1
elif ins == '8': #call
dst = data_reverse(s[2:])
reg['rsp'] -= 1
mem[reg['rsp']] = pc + 1
pc = dst
elif ins == '9': # ret
pc = mem[reg['rsp']]
reg['rsp'] += 1
elif ins == 'A': # pushq
ra = get_reg(s[3])
rb = get_reg(s[4])
reg['rsp'] -= 1
mem[reg['rsp']] = reg[ra]
pc += 1
elif ins == 'B': # popq
ra = get_reg(s[3])
rb = get_reg(s[4])
reg[ra] = mem[reg['rsp']]
reg['rsp'] += 1
pc += 1
return True
# 打印寄存器文件
def print_reg():
print('-'*20+"reg file"+'-'*20)
i = 0
for reg_name in reg.keys():
print("%s:%d"%(reg_name,reg[reg_name]),end='\t')
i += 1
if i % 4 == 0 or reg_name == 'r14':
print()
print('-'*20+"end"+'-'*20)
def print_mem():
print('-'*20+"mem"+'-'*20)
print('address:value')
j = 0
for i in range(len(mem)):
print("%d:%d"%(i,mem[i]),end=' ')
j += 1
if j % 16 == 0:
print()
print('\n'+'-'*20+"end"+'-'*20)
# start
flag = True
while flag and pc < len(exe_file):
flag = cycle()
print_mem()
print_reg()