初步实现编译器

This commit is contained in:
root 2024-05-02 08:54:42 +08:00
parent e4c1087290
commit c56daff802
10 changed files with 150 additions and 30 deletions

View File

@ -1,4 +1,5 @@
from error import * from error import *
CMDs = ["jmp", "jmp_if"] CMDs = ["jmp", "jmp_if"]

View File

@ -1,4 +1,5 @@
CMDs = ["eq", 'halt'] # , 'en', 'gt', 'lt', 'ge', 'le'] CMDs = ["eq", "halt"] # , 'en', 'gt', 'lt', 'ge', 'le']
def CheckArg(operand): def CheckArg(operand):
run = False run = False
@ -12,6 +13,7 @@ def CheckArg(operand):
raise BadOperand() raise BadOperand()
return run return run
def eq(self, operand): def eq(self, operand):
if CheckArg(operand) and operand[2].isRegister(): if CheckArg(operand) and operand[2].isRegister():
# 是否等于 # 是否等于
@ -21,6 +23,7 @@ def eq(self, operand):
operand[2].set(1) operand[2].set(1)
else: else:
operand[2].set(0) operand[2].set(0)
def halt(self, operand): def halt(self, operand):
return False return False

View File

@ -2,10 +2,10 @@
import program import program
from error import * from error import *
CMDs = ["ldr", "str"] CMDs = ["ldr", "str", 'ldrb']
def ldr(self, operand:program.Operand): def ldr(self, operand: program.Operand):
if operand[0].isRegister() and operand[1].isMemory(): if operand[0].isRegister() and operand[1].isMemory():
operand[0].set(operand[1].get()) operand[0].set(operand[1].get())
else: else:
@ -17,3 +17,4 @@ def str(self, operand):
operand[1].set(operand[0].get()) operand[1].set(operand[0].get())
else: else:
raise BadOperand() raise BadOperand()

View File

@ -1,6 +1,8 @@
from error import * from error import *
CMDs = ["add", "sub", "mul", "div"] CMDs = ["add", "sub", "mul", "div"]
def CheckArg(operand): def CheckArg(operand):
run = False run = False
if operand[0].isRegister(): if operand[0].isRegister():
@ -12,21 +14,23 @@ def CheckArg(operand):
else: else:
raise BadOperand() raise BadOperand()
return run return run
def add(self, operand): def add(self, operand):
run = CheckArg(operand) run = CheckArg(operand)
if run: if run:
a = operand[0].get() a = operand[0].get()
b = operand[1].get() b = operand[1].get()
operand[0].set(a + b) operand[0].set(a + b)
def sub(self, operand): def sub(self, operand):
run = CheckArg(operand) run = CheckArg(operand)
if run: if run:
a = operand[0].get() a = operand[0].get()
b = operand[1].get() b = operand[1].get()
operand[0].set(a - b) operand[0].set(a - b)
def mul(self, operand): def mul(self, operand):
run = CheckArg(operand) run = CheckArg(operand)
@ -34,7 +38,7 @@ def mul(self, operand):
a = operand[0].get() a = operand[0].get()
b = operand[1].get() b = operand[1].get()
operand[0].set(a * b) operand[0].set(a * b)
def div(self, operand): def div(self, operand):
run = CheckArg(operand) run = CheckArg(operand)
@ -42,4 +46,3 @@ def div(self, operand):
a = operand[0].get() a = operand[0].get()
b = operand[1].get() b = operand[1].get()
operand[0].set(a // b) operand[0].set(a // b)

10
CPU.py
View File

@ -22,12 +22,14 @@ class Core:
self.pc = 0 # 程序计数器 self.pc = 0 # 程序计数器
self.stack = queue.LifoQueue(maxsize=10 * self.registers.size) # 栈 self.stack = queue.LifoQueue(maxsize=10 * self.registers.size) # 栈
self.ASMModule = []
self.ASMs = {} self.ASMs = {}
for file in pathlib.Path("ASM").iterdir(): for file in pathlib.Path("ASM").iterdir():
if file.is_dir(): if file.is_dir():
continue continue
if str(file).split('.')[-1] not in ['py', 'pyc', 'pyd', 'so']:
continue
module = "ASM." + file.name.split(".")[0] module = "ASM." + file.name.split(".")[0]
module = importlib.import_module(module) module = importlib.import_module(module)
for cmd in module.CMDs: for cmd in module.CMDs:
@ -35,7 +37,7 @@ class Core:
def loadProgram(self, code): def loadProgram(self, code):
# 加载程序至cmdMemroy # 加载程序至cmdMemroy
self.cmdMemory[: len(code)] = code self.cmdMemory.write_batch(0,code)
def fetchInstruction(self): def fetchInstruction(self):
# 取指令 # 取指令
@ -75,7 +77,7 @@ class Core:
else: else:
raise InvalidInstruction() raise InvalidInstruction(instruction)
def run(self): def run(self):
# 开始执行 # 开始执行
@ -117,7 +119,7 @@ class CPU(Core):
if __name__ == "__main__": if __name__ == "__main__":
cpu = CPU(registers=64, dtMemory=1024, cmdMemory=1024) cpu = CPU(registers=64, dtMemory=1024, cmdMemory=10)
program.Operand(["r0"], cpu)[0].set(2) program.Operand(["r0"], cpu)[0].set(2)
f = open('Example/加法器.txt') f = open('Example/加法器.txt')
code = f.read().split('\n') code = f.read().split('\n')

51
Compiler.py Normal file
View File

@ -0,0 +1,51 @@
from Device import Codec
import time
class Compiler:
def __init__(self, codes, filename='a.out'):
self.filename = filename
self.data = []
for i in codes:
self.data.append(Codec.str2int(i))
self.write()
def write(self):
# 打开文件,以二进制写入模式打开
with open(self.filename, 'wb') as f:
maxNum = max(self.data)
byte_representation = (maxNum.bit_length() + 7) // 8
if byte_representation > 139:
raise MemoryError()
# 写入整数数据
f.write(b'\x5a\xe3'+byte_representation.to_bytes(1, 'little'))
for num in self.data:
# 将整数转换为字节,并写入文件
f.write(num.to_bytes(byte_representation , 'little')) # 假设每个整数都用4个字节表示
def read(self):
int_data_read = [] # 用于存储读取的整数数据
# 打开文件,以二进制读取模式打开
with open(self.filename, 'rb') as f:
# 读取整数数据
MagicNumber = f.read(2)
size = int.from_bytes(f.read(1), 'little')
while True:
# 从文件中读取4个字节并将其转换为整数
int_bytes = f.read(size)
if not int_bytes: # 如果读取完整个文件,则退出循环
break
int_value = int.from_bytes(int_bytes, 'little') # 假设之前用little-endian序列化
int_value = Codec.int2list(int_value)
int_value = Codec.int2str(int_value)
int_data_read.append(int_value)
return int_data_read
start = time.time()
c = Compiler(["l","h",'kakshdhsh sjjsvav'])
print(time.time()-start)
print(list(c.read()))

View File

@ -1,7 +1,56 @@
def byte2int(dt: bytes): from functools import lru_cache
import math
def str2int(dt: str):
a = []
maxInt = 0
# 遍历输入的字符串
for i in dt: for i in dt:
yield i # 这将直接生成每个字节 # 使用ord函数将每个字符转换为对应的ASCII码生成整数流
this = ord(i)
if this >maxInt:
maxInt = this
a.append(str(this))
IntSize = len(str(maxInt))
out = str(IntSize)
for i in a:
i.zfill(IntSize)
# 将处理后的整数字符串添加到输出字符串中
out += i
return int(out)
def int2bytes(dt: list[int]): def int2str(dt: list[int]):
# 遍历整数列表
a = []
for i in dt: for i in dt:
yield i.to_bytes(1, byteorder='big') # 将整数转换为字节 # 使用chr函数将每个整数转换为对应的字符生成字节流
a.append(chr(i))
return a
def list2int(dt: list[str]):
# 防止第一个数为零
maxInt = max(dt)
IntSize = len(str(maxInt))
out = str(IntSize)
# 遍历整数列表
for i in dt:
# 将整数转换为字符串
i = str(i)
# 如果字符串长度小于3则在前面补0使其长度为3
if len(i) < IntSize:
while len(i) < IntSize:
i = '0' + i
# 将处理后的整数字符串添加到输出字符串中
out += i
# 将结果字符串转换为整数并返回
return int(out)
def int2list(dt: int):
# 将整数转换为字符串,并去掉前面的'100'
size = int(str(dt)[0])
dt = str(dt)[1:]
# 将字符串按照每3个字符分割为子列表
sub_lists = [dt[i:i+size] for i in range(0, len(dt), size)]
# 遍历子列表并将其转换为整数后返回
for i in sub_lists:
yield int(i)

View File

@ -19,15 +19,15 @@ class Memory:
if index > self.size: if index > self.size:
raise AddressError() raise AddressError()
self.data[index] = val self.data[index] = val
def write_batch(self, start ,dt:list[int]): def write_batch(self, start, dt: list[int]):
if start + len(dt) > self.size: if start + len(dt) > self.size:
raise OutOfMemory('内存用尽') raise OutOfMemory("内存用尽")
for i in dt: for i in dt:
self.write(start, i) self.write(start, i)
start += 1 start += 1
def __len__(self): def __len__(self):
return self.size return self.size

View File

@ -1,17 +1,22 @@
class dtMemoryError(Exception): class dtMemoryError(Exception):
pass pass
class AddressError(dtMemoryError): class AddressError(dtMemoryError):
pass pass
class OutOfMemory(dtMemoryError): class OutOfMemory(dtMemoryError):
pass pass
class InstructionError(Exception): class InstructionError(Exception):
pass pass
class InvalidInstruction(InstructionError): class InvalidInstruction(InstructionError):
pass pass
class BadOperand(InstructionError): class BadOperand(InstructionError):
pass pass

View File

@ -4,6 +4,11 @@ from error import *
class Program: class Program:
def __init__(self, code: str): def __init__(self, code: str):
self.codelist = code.split("\n") self.codelist = code.split("\n")
self.res = []
def parser(self):
for i in self.codelist:
print(i)
class BaseArg: class BaseArg:
@ -61,7 +66,7 @@ class Operand:
def __init__(self, operList, cpu): def __init__(self, operList, cpu):
self.List = [] self.List = []
for i in operList: for i in operList:
if i[0] == "r": if i[0] == "r":
self.List.append(RegisterArg(int(i[1:]), cpu)) self.List.append(RegisterArg(int(i[1:]), cpu))
elif i[0:2] == "0x": elif i[0:2] == "0x":
@ -69,6 +74,6 @@ class Operand:
self.List.append(MemoryArg(index, cpu)) self.List.append(MemoryArg(index, cpu))
elif i.isdigit(): elif i.isdigit():
self.List.append(ImmediateArg(int(i))) self.List.append(ImmediateArg(int(i)))
def __getitem__(self, key: int): def __getitem__(self, key: int):
return self.List[key] return self.List[key]