一、 内存间接寻址实现
- 扩展寻址模式
直接寻址 vs 间接寻址
python
原直接寻址:地址为立即数
def direct_addressing(addr):
"""直接寻址:[5] 表示内存地址5"""
return MEMORY[int(addr)]
新增间接寻址:地址来自寄存器
def indirect_addressing(reg):
"""间接寻址:[BX] 表示内存地址为BX寄存器中的值"""
addr = REGISTERS[reg]
if 0 <= addr < len(MEMORY):
return MEMORY[addr]
else:
raise MemoryError(f"无效内存地址: {addr}")
2. 增强MOV指令
python
def mov_enhanced(target, source):
"""增强的MOV指令,支持多种寻址模式"""
# 获取源操作数值
if source in REGISTERS:src_value = REGISTERS[source]
elif source.startswith('[') and source.endswith(']'):# 处理内存寻址inner = source[1:-1]if inner in REGISTERS:# 间接寻址:如 [BX]src_value = indirect_addressing(inner)elif inner.isdigit():# 直接寻址:如 [5]src_value = direct_addressing(inner)else:raise ValueError(f"无效内存寻址: {source}")
elif source.isdigit() or (source.startswith('-') and source[1:].isdigit()):# 立即数src_value = int(source)
else:raise ValueError(f"无效源操作数: {source}")# 设置目标操作数
if target in REGISTERS:REGISTERS[target] = src_value
elif target.startswith('[') and target.endswith(']'):inner = target[1:-1]if inner in REGISTERS:# 间接寻址目标:如 [BX]addr = REGISTERS[inner]if 0 <= addr < len(MEMORY):MEMORY[addr] = src_valueelse:raise MemoryError(f"无效内存地址: {addr}")elif inner.isdigit():# 直接寻址目标:如 [5]MEMORY[int(inner)] = src_valueelse:raise ValueError(f"无效目标操作数: {target}")
else:raise ValueError(f"无效目标操作数: {target}")
二、 中断系统实现
- 中断向量表
python
中断向量表:中断号 -> 处理程序入口地址
IVT = {} # Interrupt Vector Table
定义系统调用中断号
SYS_INT_PRINT = 0x10 # 打印字符串
SYS_INT_READ = 0x16 # 读取输入
SYS_INT_EXIT = 0x21 # 程序退出
初始化中断向量表
def init_interrupts():
IVT[SYS_INT_PRINT] = 'INT_PRINT_HANDLER'
IVT[SYS_INT_READ] = 'INT_READ_HANDLER'
IVT[SYS_INT_EXIT] = 'INT_EXIT_HANDLER'
# 注册中断处理程序标签
LABELS['INT_PRINT_HANDLER'] = len(程序) # 假设已定义程序列表
LABELS['INT_READ_HANDLER'] = len(程序) + 20 # 示例偏移
LABELS['INT_EXIT_HANDLER'] = len(程序) + 40
- 中断触发机制
python
中断状态管理
INTERRUPT_FLAGS = {
'IF': 1, # 中断允许标志,1=允许中断
'NMI': 0, # 不可屏蔽中断请求
'IRQ': [] # 中断请求队列
}
def trigger_interrupt(int_num):
"""触发指定中断"""
if INTERRUPT_FLAGS['IF'] == 0 and int_num not in [0, 1, 2]: # 某些中断不可屏蔽
return
# 将中断号加入请求队列
INTERRUPT_FLAGS['IRQ'].append(int_num)
def check_interrupts():
"""检查并处理中断请求"""
if INTERRUPT_FLAGS['IF'] == 1 and INTERRUPT_FLAGS['IRQ']:
int_num = INTERRUPT_FLAGS['IRQ'].pop(0)
handle_interrupt(int_num)
3. 中断处理流程
python
def int_instruction(int_num):
"""INT指令:软件中断"""
# 保存现场
push(str(PC)) # 返回地址
push(str(REGISTERS['AX'])) # 保存寄存器
push(str(REGISTERS['BX']))
push(str(REGISTERS['CX']))
push(str(REGISTERS['DX']))
# 关中断,防止嵌套(简化模型)
old_if = INTERRUPT_FLAGS['IF']
INTERRUPT_FLAGS['IF'] = 0# 跳转到中断处理程序
if int_num in IVT:handler_label = IVT[int_num]global PCPC = LABELS[handler_label] - 1 # -1因为执行后会PC+1
else:raise ValueError(f"未定义的中断号: {int_num}")# 中断返回时会恢复现场
-
中断返回指令
python
def iret():
"""中断返回指令"""恢复寄存器
pop('DX')
pop('CX')
pop('BX')
pop('AX')恢复返回地址
pop('AX') # 临时存储到AX
global PC
PC = REGISTERS['AX'] - 1 # -1因为执行后会PC+1恢复中断标志
INTERRUPT_FLAGS['IF'] = 1
三、 输入输出系统 -
端口映射I/O
python
I/O端口模拟
PORTS = {
0x60: None, # 键盘数据端口
0x64: 0, # 键盘状态端口
0x3F8: '', # 串口数据
0x3F9: 0, # 串口状态
}
IN/OUT指令
def in_instruction(port, reg):
"""从端口读取数据到寄存器"""
port_num = int(port, 16) if isinstance(port, str) else port
if port_num in PORTS:
REGISTERS[reg] = PORTS[port_num]
else:
REGISTERS[reg] = 0
def out_instruction(port, source):
"""从寄存器写入数据到端口"""
port_num = int(port, 16) if isinstance(port, str) else port
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
if port_num in PORTS:PORTS[port_num] = value
- 系统调用模拟
python
中断处理程序:系统调用实现
系统调用程序 = [
# INT 0x10 处理程序 - 打印字符串
'INT_PRINT_HANDLER:',
'PUSH AX', # 保存寄存器
'PUSH BX',
'PUSH CX',
'MOV CX, 0', # 字符串长度计数器
'MOV BX, DX', # DX中为字符串地址(通过寄存器传递参数)'PRINT_LOOP:',
'MOV AL, [BX]', # 读取一个字符
'CMP AL, 0', # 检查字符串结束符
'JE PRINT_DONE',# 输出字符(简化为打印到控制台)
'OUT 0x3F8, AL', # 输出到串口(模拟)
'ADD BX, 1', # 下一个字符
'ADD CX, 1',
'JMP PRINT_LOOP','PRINT_DONE:',
'POP CX',
'POP BX',
'POP AX',
'IRET',# INT 0x16 处理程序 - 读取键盘输入
'INT_READ_HANDLER:',
'PUSH AX',
'IN AL, 0x60', # 从键盘端口读取
'MOV [DI], AL', # 存储到DI指向的内存(参数传递)
'POP AX',
'IRET',# INT 0x21 处理程序 - 程序退出
'INT_EXIT_HANDLER:',
'MOV [0xFFF], 1', # 设置退出标志
'IRET'
]