寒假学习笔记1.15
一、 扩展指令集实现
-
算术运算扩展
减法指令(SUB)
python
def sub(reg, source):
"""减法运算:reg = reg - source"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
else:
raise ValueError("无效源操作数")设置标志位
FLAGS['CF'] = 1 if value > REGISTERS[reg] else 0 # 借位标志
FLAGS['ZF'] = 1 if REGISTERS[reg] - value == 0 else 0 # 零标志REGISTERS[reg] -= value
乘法指令(MUL)和除法指令(DIV)
python
def mul(reg, source):
"""乘法运算:reg = reg * source"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
REGISTERS[reg] *= value
def div(reg, source):
"""除法运算:reg = reg // source"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
if value == 0:
raise ValueError("除零错误")
REGISTERS[reg] //= value
2. 逻辑运算指令
与运算(AND)、或运算(OR)、非运算(NOT)
python
def and_op(reg, source):
"""按位与运算"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
REGISTERS[reg] &= value
FLAGS['ZF'] = 1 if REGISTERS[reg] == 0 else 0
def or_op(reg, source):
"""按位或运算"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
REGISTERS[reg] |= value
FLAGS['ZF'] = 1 if REGISTERS[reg] == 0 else 0
def not_op(reg):
"""按位非运算"""
REGISTERS[reg] = ~REGISTERS[reg]
二、 栈机制实现
- 栈内存分配
python
扩展内存模型,分配栈空间
MEMORY_SIZE = 256
STACK_SIZE = 64
MEMORY = [0] * MEMORY_SIZE # 0-191为通用内存,192-255为栈空间
栈指针寄存器
REGISTERS['SP'] = MEMORY_SIZE - 1 # 栈指针指向栈顶
REGISTERS['BP'] = MEMORY_SIZE - 1 # 基址指针
2. 栈操作指令
PUSH(压栈)
python
def push(source):
"""将数据压入栈"""
if source in REGISTERS:
value = REGISTERS[source]
elif source.isdigit():
value = int(source)
# 栈从高地址向低地址增长
MEMORY[REGISTERS['SP']] = value
REGISTERS['SP'] -= 1
# 栈溢出检查
if REGISTERS['SP'] < MEMORY_SIZE - STACK_SIZE:
raise MemoryError("栈溢出")
POP(出栈)
python
def pop(target):
"""从栈中弹出数据到目标寄存器"""
# 栈下溢检查
if REGISTERS['SP'] >= MEMORY_SIZE - 1:
raise MemoryError("栈下溢")
REGISTERS['SP'] += 1
value = MEMORY[REGISTERS['SP']]
if target in REGISTERS:
REGISTERS[target] = value
else:
raise ValueError("目标必须是寄存器")
三、 子程序调用机制
-
CALL和RET指令
python
def call(label):
"""调用子程序"""保存返回地址(下一条指令的地址)
return_address = PC + 1
push(str(return_address))跳转到子程序
if label in LABELS:
global PC
PC = LABELS[label] - 1 # -1因为执行后会PC+1
else:
raise ValueError(f"未定义的标签: {label}")
def ret():
"""从子程序返回"""
# 从栈中弹出返回地址
pop('AX') # 临时存储到AX
global PC
PC = REGISTERS['AX'] - 1 # -1因为执行后会PC+1
2. 栈帧管理
python
进入子程序时保存基址指针并建立新栈帧
def enter():
"""进入子程序,建立新栈帧"""
push('BP') # 保存原BP
REGISTERS['BP'] = REGISTERS['SP'] # 新栈帧基址
def leave():
"""离开子程序,恢复原栈帧"""
REGISTERS['SP'] = REGISTERS['BP'] # 恢复栈指针
pop('BP') # 恢复原BP
四、 综合示例程序
- 计算阶乘的子程序
python
汇编程序:计算5的阶乘
程序 = [
'MOV AX, 5', # 设置参数
'CALL FACTORIAL', # 调用阶乘函数
'MOV [0], AX', # 存储结果
'HLT', # 停机
# 阶乘子程序
'FACTORIAL:',
'PUSH BP', # 保存原BP
'MOV BP, SP', # 建立新栈帧
'PUSH BX', # 保存BX
'MOV BX, AX', # 备份参数
'CMP AX, 1', # 比较AX和1
'JLE BASE_CASE', # 如果AX<=1,跳转到基本情况
# 递归调用
'SUB AX, 1', # AX = n-1
'CALL FACTORIAL', # 递归调用
'MUL AX, BX', # AX = n * factorial(n-1)
'JMP END_FACT',
'BASE_CASE:',
'MOV AX, 1', # factorial(1) = 1
'END_FACT:',
'POP BX', # 恢复BX
'POP BP', # 恢复BP
'RET' # 返回
]
2. 函数调用中的栈变化
text
初始状态:
SP=255, BP=255
执行CALL FACTORIAL后:
SP=254, MEMORY[255]=返回地址
执行PUSH BP后:
SP=253, MEMORY[254]=原BP值
执行MOV BP, SP后:
BP=253 (新栈帧基址)
执行PUSH BX后:
SP=252, MEMORY[253]=BX的原值
...递归调用会继续压栈...
每次RET返回时,会逆向恢复栈状态
浙公网安备 33010602011771号