在计算机体系结构中,主存(内存)和寄存器是两种非常重要的存储设备。主存用于存储程序和数据,而寄存器则用于快速存取数据。为了更好地理解它们的工作原理,使用 Python 模拟一个简单的主存和寄存器文件系统。
一、实现思路
1. 主存模拟
主存是一个按字节编址的存储设备,每个字节可以存储 8 位二进制数据。使用 Python 的列表来模拟主存,列表的每个元素表示一个二进制位(0
或 1
)。通过这种方式,模拟内存的读写操作。
2. 寄存器文件模拟
寄存器文件是 CPU 内部的高速存储设备,通常由多个寄存器组成。每个寄存器可以存储固定长度的二进制数据。使用 Python 的列表来模拟寄存器文件,列表的每个元素表示一个32
位的二进制字符串。
3. 功能实现
- 主存:支持按字节读写内存,确保地址对齐和数据长度正确
- 寄存器文件:支持按寄存器索引读写数据,确保数据长度为 32 位
二、技术细节
1. 主存模拟
主存的核心是一个字符数组mem
,每个元素存储 0
或 1
。我们实现了以下功能:
- load 函数:根据指定的地址和字节数读取内存,返回二进制字符串
- store 函数:将二进制字符串写入内存,确保地址对齐和数据长度正确
- print_memory_range 函数:打印指定内存地址范围内的值
# 申请一个字符数组模拟内存,每个元素只存储 0 或 1
mem_size = 1 * 1024 * 1024 * 1024 # 1 GB
mem = ['0'] * mem_size # 初始化内存,全部为 '0'
def load(address, byte_count):
"""根据指定的字节数(byte_count)读取内存并返回二进制字符串"""
start = int(address, 2) # 将地址从二进制字符串转换为整数
end = start + byte_count * 8 # 计算结束位置(按比特)
return ''.join(mem[start:end]) # 返回指定字节数的二进制字符串
def store(address, binary_value, byte_count):
"""
将地址和二进制字符串写入内存
:param address: 二进制字符串,表示写入的起始地址
:param binary_value: 二进制字符串,表示要写入的数据
:param byte_count: 写入的字节数
"""
start = int(address, 2) # 将地址从二进制字符串转换为整数
# 检查地址是否对齐
if start % 8 != 0:
raise ValueError(f"地址 {address} 不是 8 的倍数,无法按字节编址写入。")
# 检查二进制字符串的长度是否匹配字节数
if len(binary_value) != byte_count * 8:
raise ValueError(f"二进制字符串的长度必须是 {byte_count * 8} 位,当前长度为 {len(binary_value)} 位。")
# 将二进制字符串逐位写入内存
for i in range(len(binary_value)):
mem[start + i] = binary_value[i]
def print_memory_range(start, byte_count):
"""打印指定内存地址范围内的值"""
start = int(start, 2) # 将起始地址转换为整数
end = start + byte_count * 8 # 计算结束位置(按比特)
print(f"Memory values (from Address {start} to {end - 1}):")
for i in range(start, end, 32): # 每次打印 32 位
binary_value = load(format(i, '032b'), 4) # 读取 32 位(4 字节)
print(f"Address {format(i, '032b')}: {binary_value}")
测试程序
try:
# 写入数据(地址和32位二进制字符串,4字节)
store('00000000000000000000000000000000', '10010000000000000000000000000000', 4)
store('00000000000000000000000000100000', '10010000001000000000000001100100', 4)
store('00000000000000000000000001000000', '10010000010000000000000000000000', 4)
# 打印内存范围
print_memory_range('00000000000000000000000000000000', 4) # 打印前 4 字节
except ValueError as e:
print(e)
2. 寄存器文件模拟
寄存器文件的核心是一个列表regs
,每个元素是一个 32 位的二进制字符串。我们实现了以下功能:
- read 函数:读取指定寄存器的值,返回 32 位二进制字符串
- write 函数:将 32 位二进制字符串写入指定寄存器
- print_registers 函数:打印所有寄存器的值
# 模拟32个通用寄存器,每个寄存器为32位二进制字符串
reg_size = 32 # 寄存器数量
regs = ['0' * 32 for _ in range(reg_size)] # 初始化32个寄存器,每个寄存器为32位二进制字符串
# 全局变量:指令寄存器IR、程序计数器PC、标志寄存器CF
ir = '0' * 32 # 指令寄存器
pc = '0' * 32 # 程序计数器
cf = '0' * 32 # 标志寄存器
def read(index_bin):
"""读取指定索引的寄存器,返回32位二进制字符串"""
index = int(index_bin, 2) # 将32位二进制字符串转换为整数
if index < 0 or index >= reg_size:
raise IndexError(f"寄存器索引 {index} 超出范围(0 到 {reg_size - 1})。")
return regs[index] # 返回寄存器的32位二进制字符串
def write(index_bin, binary_str):
"""将32位二进制字符串写入指定寄存器"""
index = int(index_bin, 2) # 将32位二进制字符串转换为整数
if index < 0 or index >= reg_size:
raise IndexError(f"寄存器索引 {index} 超出范围(0 到 {reg_size - 1})。")
if len(binary_str) != 32:
raise ValueError("输入的二进制字符串必须是32位。")
regs[index] = binary_str # 将32位二进制字符串写入寄存器
def get_register_value(index_bin):
"""返回指定寄存器的值(十进制和二进制)"""
value = read(index_bin)
return f"Register index {index_bin} : Decimal: {int(value, 2)}, Binary: {value}"
def print_registers():
"""打印所有寄存器的值,包括指令寄存器、程序计数器和标志寄存器"""
print("Registers values:")
for i in range(reg_size):
index_bin = format(i, '032b') # 以32位二进制格式获取寄存器编号
value = read(index_bin)
print(f"Register index {index_bin} ({int(index_bin, 2):2d}): Decimal: {int(value, 2):10d}, Binary: {value}")
print(f"Instruction Register (IR): Binary: {ir}")
print(f"Program Counter (PC): Binary: {pc}, Decimal: {int(pc, 2)}")
print(f"Flag Register (CF): Binary: {cf}")
测试程序
def run_tests():
# 初始化寄存器
print("Initial state:")
print_registers()
# 写入值到寄存器
print("\nWriting values to registers...")
write(format(0, '032b'), '00000000000000000000000000000001') # 写入1到寄存器0
write(format(1, '032b'), '00000000000000000000000000000010') # 写入2到寄存器1
write(format(2, '032b'), '00000000000000000000000000000011') # 写入3到寄存器2
# 读取并打印寄存器值
print("\nAfter writing values:")
print_registers()
# 获取特定寄存器值
print("\nGetting register values:")
print(get_register_value(format(0, '032b'))) # 获取寄存器0的值
print(get_register_value(format(1, '032b'))) # 获取寄存器1的值
print(get_register_value(format(2, '032b'))) # 获取寄存器2的值
# 尝试写入超出范围的寄存器
try:
write(format(32, '032b'), '00000000000000000000000000000100') # 超出范围,写入到寄存器32
except IndexError as e:
print(f"Error: {e}")
# 尝试写入非32位二进制字符串
try:
write(format(3, '032b'), '000000000000000000000000000001') # 非32位二进制字符串
except ValueError as e:
print(f"Error: {e}")
三、示例程序
我们可以使用上述模拟器实现一个简单的汇编程序:
Load r1, #0
Load r2, #1
Add r3, r1, r2
Store r3, #3
import ALU
import memory
import registerfile
print('=' * 55 + '初始状态' + '=' * 55)
registerfile.print_registers()
memory.print_memory_range('00000000000000000000000000100000', 4)
registerfile.write("00000000000000000000000000000000", "00000000000000000000000000000100")
registerfile.write("00000000000000000000000000000001", "00000000000000000000000000001001")
rs1_val = registerfile.read("00000000000000000000000000000000")
rs2_val = registerfile.read("00000000000000000000000000000001")
rd = ALU.add_binary(rs1_val, rs2_val)
registerfile.write("00000000000000000000000000000010", rd)
memory.store("00000000000000000000000000100000", rd, 4)
print('=' * 55 + '程序执行后状态' + '=' * 55)
registerfile.print_registers()
memory.print_memory_range('00000000000000000000000000100000', 4)
测试结果
=======================================================初始状态=======================================================
Registers values:
Register index 00000000000000000000000000000000 ( 0): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000001 ( 1): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000010 ( 2): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000011 ( 3): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000100 ( 4): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000101 ( 5): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000110 ( 6): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000111 ( 7): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001000 ( 8): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001001 ( 9): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001010 (10): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001011 (11): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001100 (12): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001101 (13): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001110 (14): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001111 (15): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010000 (16): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010001 (17): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010010 (18): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010011 (19): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010100 (20): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010101 (21): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010110 (22): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010111 (23): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011000 (24): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011001 (25): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011010 (26): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011011 (27): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011100 (28): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011101 (29): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011110 (30): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011111 (31): Decimal: 0, Binary: 00000000000000000000000000000000
Instruction Register (IR): Binary: 00000000000000000000000000000000
Program Counter (PC): Binary: 00000000000000000000000000000000, Decimal: 0
Flag Register (CF): Binary: 00000000000000000000000000000000
Memory values (from Address 32 to 63):
Address 00000000000000000000000000100000: 00000000000000000000000000000000
=======================================================程序执行后状态=======================================================
Registers values:
Register index 00000000000000000000000000000000 ( 0): Decimal: 4, Binary: 00000000000000000000000000000100
Register index 00000000000000000000000000000001 ( 1): Decimal: 9, Binary: 00000000000000000000000000001001
Register index 00000000000000000000000000000010 ( 2): Decimal: 13, Binary: 00000000000000000000000000001101
Register index 00000000000000000000000000000011 ( 3): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000100 ( 4): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000101 ( 5): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000110 ( 6): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000000111 ( 7): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001000 ( 8): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001001 ( 9): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001010 (10): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001011 (11): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001100 (12): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001101 (13): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001110 (14): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000001111 (15): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010000 (16): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010001 (17): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010010 (18): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010011 (19): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010100 (20): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010101 (21): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010110 (22): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000010111 (23): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011000 (24): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011001 (25): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011010 (26): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011011 (27): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011100 (28): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011101 (29): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011110 (30): Decimal: 0, Binary: 00000000000000000000000000000000
Register index 00000000000000000000000000011111 (31): Decimal: 0, Binary: 00000000000000000000000000000000
Instruction Register (IR): Binary: 00000000000000000000000000000000
Program Counter (PC): Binary: 00000000000000000000000000000000, Decimal: 0
Flag Register (CF): Binary: 00000000000000000000000000000000
Memory values (from Address 32 to 63):
Address 00000000000000000000000000100000: 00000000000000000000000000001101
总结
通过 Python 模拟主存和寄存器文件系统,可以更好地理解计算机底层的工作原理。这个模拟器虽然简单,但涵盖了内存和寄存器的基本操作,为进一步学习计算机体系结构打下了基础。