目标代码形式主要包括三种:汇编语言形式、绝对机器指令代码和可再定位机器代码。
- 汇编语言形式:以助记符表示操作码,符号表示地址,便于人工阅读与调试。通常作为编译器输出的中间步骤,后续可通过汇编器转换为机器代码。
- 绝对机器代码:生成后可直接加载到内存固定地址执行,适用于简单的“load-and-go”系统(如早期小型系统或嵌入式环境),无需链接或重定位过程。
- 可再定位机器代码:包含未解析的符号引用和相对地址,允许在不同内存位置加载并与其他模块链接,是现代编译器常用的输出格式,支持模块化编程与动态链接。
寄存器分配是目标代码生成阶段的关键任务。由于CPU寄存器数量有限但访问速度极快,需通过算法(如图着色法、线性扫描)将频繁使用的变量尽可能分配至寄存器,减少内存访问次数,从而提升程序运行效率。
计算次序的选择影响执行性能。例如,在表达式求值中应优先计算副作用小、使用频率高的子表达式,并结合目标机架构特性(如指令流水线、寻址模式)优化指令序列顺序,实现高效执行。
解释程序的基本原理是不生成独立的目标程序,而是直接执行源程序或其中间表示。其与编译程序的主要差异在于:
- 编译程序先将源程序完整翻译为目标代码,再执行;
- 解释程序逐条分析并立即执行语句。
解释程序的实现方式有两种:
- 直接解释执行源程序:如 BASIC 解释器,边词法/语法分析边执行,开发简单但效率低;
- 基于中间代码的解释执行:如 PASCAL-P 系统,先将源程序编译为紧凑的中间代码(P-code),再由解释器执行该代码,提高了可移植性和执行效率。
# 示例:一个简单的中间代码解释器框架(示意)
class Interpreter:
def __init__(self, bytecode):
self.bytecode = bytecode # 中间代码列表
self.pc = 0 # 程序计数器
self.stack = [] # 操作数栈
def run(self):
while self.pc < len(self.bytecode):
instruction = self.bytecode[self.pc]
self.pc += 1
op = instruction[0]
if op == "LOAD":
self.stack.append(instruction[1])
elif op == "ADD":
b, a = self.stack.pop(), self.stack.pop()
self.stack.append(a + b)
elif op == "PRINT":
print(self.stack.pop())
else:
raise RuntimeError(f"Unknown opcode: {op}")



被折叠的 条评论
为什么被折叠?



