中间代码生成实战(三)—— 函数
核心知识点讲解
1. 函数的中间代码表示
函数的中间代码生成涉及多个方面:
- 函数声明:声明函数的名称、参数类型和返回类型
- 函数定义:定义函数的实现,包括序言(prologue)和尾声(epilogue)
- 函数调用:生成调用函数的代码,包括参数传递和返回值处理
2. 栈帧布局
栈帧是函数执行时在栈上分配的内存区域,用于存储:
- 返回地址:函数执行完毕后要返回到的地址
- 参数:传递给函数的参数
- 局部变量:函数内定义的局部变量
- 临时变量:计算过程中产生的临时值
- 保存的寄存器:函数执行前需要保存的寄存器值
栈帧的典型布局如下:
高地址
┌─────────────────┐
│ 返回地址 │
├─────────────────┤
│ 参数 N │
│ ... │
│ 参数 1 │
├─────────────────┤
│ 局部变量 1 │
│ 局部变量 2 │
│ ... │
│ 临时变量 │
├─────────────────┤
│ 保存的寄存器 │
└─────────────────┘
低地址3. 参数传递方式
常见的参数传递方式有:
- 值传递:将参数的值复制到栈帧中
- 引用传递:将参数的地址传递给函数
- 寄存器传递:使用寄存器传递参数(适用于少量参数)
4. 函数调用的三地址码生成规则
对于函数调用 result = func(a1, a2, ..., an),生成规则如下:
- 计算所有实参的值,将结果存储在临时变量中
- 将实参的值传递到栈帧或寄存器中
- 生成函数调用指令:
call func - 函数执行完毕后,从返回值寄存器或栈中获取返回值
- 将返回值存储在
result中
5. 函数定义的三地址码生成规则
对于函数定义 type func(p1, p2, ..., pn) { body },生成规则如下:
- 序言:保存寄存器,分配栈帧空间
- 参数处理:将栈上的参数复制到局部变量
- 函数体:生成函数体的三地址码
- 返回值处理:将返回值存储到指定位置
- 尾声:恢复寄存器,释放栈帧空间,返回
实用案例分析
案例:实现函数的中间代码生成
我们将扩展之前的编译器,使其能够处理函数定义和调用。
步骤 1:扩展 AST 节点类型
首先,我们需要扩展 AST 节点类型,以支持函数定义和调用:
class FunctionDefinition(ASTNode):
"""函数定义节点"""
def __init__(self, name, parameters, return_type, body):
self.name = name
self.parameters = parameters
self.return_type = return_type
self.body = body
def __repr__(self):
return f"FunctionDefinition('{self.name}', {repr(self.parameters)}, '{self.return_type}', {repr(self.body)})"
class FunctionCall(ASTNode):
"""函数调用节点"""
def __init__(self, name, arguments):
self.name = name
self.arguments = arguments
def __repr__(self):
return f"FunctionCall('{self.name}', {repr(self.arguments)})"
class ReturnStatement(ASTNode):
"""返回语句节点"""
def __init__(self, expr=None):
self.expr = expr
def __repr__(self):
if self.expr:
return f"ReturnStatement({repr(self.expr)})"
else:
return "ReturnStatement()"步骤 2:扩展解析器以支持函数定义和调用
现在,我们扩展解析器以支持函数定义和调用:
class Parser:
"""支持函数的解析器"""
def __init__(self, tokens):
self.tokens = tokens
self.pos = 0
def peek(self):
"""查看当前 token"""
if self.pos < len(self.tokens):
return self.tokens[self.pos]
return None
def consume(self, expected_type=None):
"""消费当前 token"""
if self.pos < len(self.tokens):
token = self.tokens[self.pos]
if expected_type and token[0] != expected_type:
raise SyntaxError(f"Expected {expected_type}, got {token[0]}")
self.pos += 1
return token
raise SyntaxError("Unexpected end of input")
def parse(self):
"""解析程序"""
statements = []
while self.peek():
statements.append(self.parse_statement())
if len(statements) == 1:
return statements[0]
else:
return Sequence(statements)
def parse_statement(self):
"""解析语句"""
token = self.peek()
if token[0] == 'if':
return self.parse_if_statement()
elif token[0] == 'while':
return self.parse_while_statement()
elif token[0] == 'for':
return self.parse_for_statement()
elif token[0] == '{':
return self.parse_block()
elif token[0] == 'return':
return self.parse_return_statement()
elif token[0] == 'int' or token[0] == 'void':
# 可能是函数定义
return_type = self.consume()[0]
if self.peek() and self.peek()[0] == 'ID':
func_name = self.consume('ID')[1]
if self.peek() and self.peek()[0] == '(':
# 是函数定义
self.consume('(')
parameters = self.parse_parameters()
self.consume(')')
body = self.parse_block()
return FunctionDefinition(func_name, parameters, return_type, body)
else:
# 是变量声明
self.pos -= 1 # 回退 ID
# 这里可以添加变量声明的解析
else:
# 检查是否是函数调用
if self.peek() and self.peek()[0] == 'ID':
id_token = self.consume('ID')
if self.peek() and self.peek()[0] == '(':
# 是函数调用
self.consume('(')
arguments = self.parse_arguments()
self.consume(')')
return FunctionCall(id_token[1], arguments)
else:
# 不是函数调用,回退
self.pos -= 1
return self.parse_assignment()
def parse_parameters(self):
"""解析函数参数"""
parameters = []
if self.peek() and self.peek()[0] != ')':
while True:
# 解析参数类型
param_type = self.consume()[0]
# 解析参数名
param_name = self.consume('ID')[1]
parameters.append((param_type, param_name))
if not (self.peek() and self.peek()[0] == ','):
break
self.consume(',')
return parameters
def parse_arguments(self):
"""解析函数实参"""
arguments = []
if self.peek() and self.peek()[0] != ')':
while True:
arguments.append(self.parse_expr())
if not (self.peek() and self.peek()[0] == ','):
break
self.consume(',')
return arguments
def parse_return_statement(self):
"""解析返回语句"""
self.consume('return')
if self.peek() and self.peek()[0] != ';':
expr = self.parse_expr()
self.consume(';')
return ReturnStatement(expr)
else:
self.consume(';')
return ReturnStatement()
# 其他方法与之前相同...
def parse_block(self):
"""解析语句块"""
self.consume('{')
statements = []
while self.peek() and self.peek()[0] != '}':
statements.append(self.parse_statement())
self.consume('}')
if len(statements) == 1:
return statements[0]
else:
return Sequence(statements)
def parse_if_statement(self):
"""解析 if-else 语句"""
self.consume('if')
self.consume('(')
condition = self.parse_expr()
self.consume(')')
true_body = self.parse_statement()
false_body = None
if self.peek() and self.peek()[0] == 'else':
self.consume('else')
false_body = self.parse_statement()
return IfStatement(condition, true_body, false_body)
def parse_while_statement(self):
"""解析 while 语句"""
self.consume('while')
self.consume('(')
condition = self.parse_expr()
self.consume(')')
body = self.parse_statement()
return WhileStatement(condition, body)
def parse_for_statement(self):
"""解析 for 语句"""
self.consume('for')
self.consume('(')
init = self.parse_assignment()
self.consume(';')
condition = self.parse_expr()
self.consume(';')
update = self.parse_assignment()
self.consume(')')
body = self.parse_statement()
return ForStatement(init, condition, update, body)
def parse_assignment(self):
"""解析赋值语句"""
target = self.parse_primary()
if self.peek() and self.peek()[0] == '=':
self.consume('=')
expr = self.parse_expr()
self.consume(';')
return Assignment(target, expr)
else:
# 如果不是赋值语句,回退
self.pos -= 1
expr = self.parse_expr()
self.consume(';')
return expr
def parse_expr(self):
"""解析表达式(处理加减和关系运算)"""
left = self.parse_term()
while self.peek() and self.peek()[0] in ('+', '-', '<', '<=', '>', '>=', '==', '!='):
op = self.consume()[0]
right = self.parse_term()
left = BinaryOp(op, left, right)
return left
def parse_term(self):
"""解析项(处理乘除)"""
left = self.parse_factor()
while self.peek() and self.peek()[0] in ('*', '/'):
op = self.consume()[0]
right = self.parse_factor()
left = BinaryOp(op, left, right)
return left
def parse_factor(self):
"""解析因子"""
return self.parse_primary()
def parse_primary(self):
"""解析基本表达式"""
token = self.peek()
if token[0] == '(':
self.consume('(')
expr = self.parse_expr()
self.consume(')')
return expr
elif token[0] == 'NUMBER':
return Constant(self.consume('NUMBER')[1])
elif token[0] == 'ID':
return Variable(self.consume('ID')[1])
elif token[0] in ('+', '-'):
op = self.consume()[0]
expr = self.parse_primary()
return UnaryOp(op, expr)
else:
raise SyntaxError(f"Unexpected token: {token}")步骤 3:扩展词法分析器以支持函数相关的关键字
我们需要扩展词法分析器以识别函数相关的关键字:
def tokenize(code):
"""将代码转换为 token 列表"""
tokens = []
i = 0
keywords = {'if', 'else', 'while', 'for', 'int', 'void', 'return'}
while i < len(code):
c = code[i]
if c.isspace():
i += 1
elif c.isdigit():
# 解析数字
num = ""
while i < len(code) and code[i].isdigit():
num += code[i]
i += 1
tokens.append(('NUMBER', int(num)))
elif c.isalpha():
# 解析标识符或关键字
id = ""
while i < len(code) and code[i].isalnum():
id += code[i]
i += 1
if id in keywords:
tokens.append((id, id))
else:
tokens.append(('ID', id))
elif c in '+-*/(){};,':
# 解析操作符、括号、分号和逗号
tokens.append((c, c))
i += 1
elif c == '=':
# 解析赋值运算符
tokens.append(('=', '='))
i += 1
elif c == '<' and i+1 < len(code) and code[i+1] == '=':
# 解析 <=
tokens.append(('<=', '<='))
i += 2
elif c == '>' and i+1 < len(code) and code[i+1] == '=':
# 解析 >=
tokens.append(('>=', '>='))
i += 2
elif c == '!' and i+1 < len(code) and code[i+1] == '=':
# 解析 !=
tokens.append(('!=', '!='))
i += 2
elif c == '=' and i+1 < len(code) and code[i+1] == '=':
# 解析 ==
tokens.append(('==', '=='))
i += 2
else:
raise SyntaxError(f"Unexpected character: {c}")
return tokens步骤 4:扩展三地址码生成器以支持函数
现在,我们扩展三地址码生成器以支持函数定义和调用:
class TACGenerator:
"""支持函数的三地址码生成器"""
def __init__(self):
self.temp_count = 0
self.label_count = 0
self.instructions = []
self.functions = [] # 存储函数定义
def new_temp(self):
"""生成新的临时变量"""
temp = f"t{self.temp_count}"
self.temp_count += 1
return temp
def new_label(self):
"""生成新的标签"""
label = f"L{self.label_count}"
self.label_count += 1
return label
def generate(self, node):
"""生成三地址码"""
if isinstance(node, Constant):
return node.value
elif isinstance(node, Variable):
return node.name
elif isinstance(node, BinaryOp):
left_val = self.generate(node.left)
right_val = self.generate(node.right)
temp = self.new_temp()
self.instructions.append(f"{temp} = {left_val} {node.op} {right_val}")
return temp
elif isinstance(node, UnaryOp):
expr_val = self.generate(node.expr)
temp = self.new_temp()
self.instructions.append(f"{temp} = {node.op} {expr_val}")
return temp
elif isinstance(node, Assignment):
target = node.target.name
expr_val = self.generate(node.expr)
self.instructions.append(f"{target} = {expr_val}")
return target
elif isinstance(node, Sequence):
for stmt in node.statements:
self.generate(stmt)
return None
elif isinstance(node, IfStatement):
self.generate_if_statement(node)
return None
elif isinstance(node, WhileStatement):
self.generate_while_statement(node)
return None
elif isinstance(node, ForStatement):
self.generate_for_statement(node)
return None
elif isinstance(node, ReturnStatement):
return self.generate_return_statement(node)
elif isinstance(node, FunctionCall):
return self.generate_function_call(node)
elif isinstance(node, FunctionDefinition):
self.generate_function_definition(node)
return None
else:
raise TypeError(f"Unknown AST node type: {type(node)}")
def generate_if_statement(self, node):
"""生成 if-else 语句的三地址码"""
# 生成条件表达式的三地址码
cond_val = self.generate(node.condition)
# 生成标签
Lfalse = self.new_label()
Lend = self.new_label()
# 生成条件跳转
self.instructions.append(f"iffalse {cond_val} goto {Lfalse}")
# 生成 true_body 的三地址码
self.generate(node.true_body)
# 生成无条件跳转
self.instructions.append(f"goto {Lend}")
# 生成 Lfalse 标签
self.instructions.append(f"{Lfalse}:")
# 生成 false_body 的三地址码
if node.false_body:
self.generate(node.false_body)
# 生成 Lend 标签
self.instructions.append(f"{Lend}:")
def generate_while_statement(self, node):
"""生成 while 语句的三地址码"""
# 生成标签
Lstart = self.new_label()
Lend = self.new_label()
# 生成 Lstart 标签
self.instructions.append(f"{Lstart}:")
# 生成条件表达式的三地址码
cond_val = self.generate(node.condition)
# 生成条件跳转
self.instructions.append(f"iffalse {cond_val} goto {Lend}")
# 生成 body 的三地址码
self.generate(node.body)
# 生成无条件跳转
self.instructions.append(f"goto {Lstart}")
# 生成 Lend 标签
self.instructions.append(f"{Lend}:")
def generate_for_statement(self, node):
"""生成 for 语句的三地址码"""
# 生成标签
Lstart = self.new_label()
Lend = self.new_label()
# 生成 init 的三地址码
self.generate(node.init)
# 生成 Lstart 标签
self.instructions.append(f"{Lstart}:")
# 生成条件表达式的三地址码
cond_val = self.generate(node.condition)
# 生成条件跳转
self.instructions.append(f"iffalse {cond_val} goto {Lend}")
# 生成 body 的三地址码
self.generate(node.body)
# 生成 update 的三地址码
self.generate(node.update)
# 生成无条件跳转
self.instructions.append(f"goto {Lstart}")
# 生成 Lend 标签
self.instructions.append(f"{Lend}:")
def generate_return_statement(self, node):
"""生成返回语句的三地址码"""
if node.expr:
# 生成表达式的三地址码
expr_val = self.generate(node.expr)
# 生成返回指令
self.instructions.append(f"return {expr_val}")
return expr_val
else:
# 生成空返回指令
self.instructions.append("return")
return None
def generate_function_call(self, node):
"""生成函数调用的三地址码"""
# 计算实参的值
arg_vals = []
for arg in node.arguments:
arg_val = self.generate(arg)
arg_vals.append(arg_val)
# 生成参数传递指令
for i, arg_val in enumerate(reversed(arg_vals)):
# 逆序压栈(假设栈传递)
self.instructions.append(f"push {arg_val}")
# 生成函数调用指令
self.instructions.append(f"call {node.name}")
# 生成清理栈的指令(假设每个参数占用 4 字节)
if arg_vals:
self.instructions.append(f"add esp, {4 * len(arg_vals)}")
# 生成临时变量存储返回值
result_temp = self.new_temp()
self.instructions.append(f"{result_temp} = eax") # 假设返回值在 eax 寄存器中
return result_temp
def generate_function_definition(self, node):
"""生成函数定义的三地址码"""
# 记录函数名
self.functions.append(node.name)
# 生成函数标签
self.instructions.append(f"{node.name}:")
# 生成序言
# 1. 保存返回地址(通常由调用者保存)
# 2. 保存 ebp 寄存器
self.instructions.append("push ebp")
# 3. 设置新的 ebp
self.instructions.append("mov ebp, esp")
# 4. 分配栈帧空间(假设每个局部变量占用 4 字节)
# 这里简化处理,实际需要根据局部变量数量计算
local_vars_count = 0 # 这里可以添加局部变量计数
if local_vars_count > 0:
self.instructions.append(f"sub esp, {4 * local_vars_count}")
# 生成参数处理代码
# 假设参数从 ebp + 8 开始(跳过返回地址和旧 ebp)
for i, (param_type, param_name) in enumerate(node.parameters):
offset = 8 + i * 4 # 每个参数 4 字节
self.instructions.append(f"{param_name} = [ebp + {offset}]")
# 生成函数体的三地址码
self.generate(node.body)
# 生成尾声
# 1. 恢复 esp
self.instructions.append("mov esp, ebp")
# 2. 恢复 ebp
self.instructions.append("pop ebp")
# 3. 返回
self.instructions.append("ret")
def get_instructions(self):
"""获取生成的三地址码指令"""
return self.instructions
def get_functions(self):
"""获取生成的函数列表"""
return self.functions步骤 5:测试函数的中间代码生成
让我们测试一下我们的编译器,看看它是否能正确生成函数的三地址码:
# 测试函数
def test_function(code):
print(f"\nTesting code:\n{code}")
# 词法分析
tokens = tokenize(code)
print(f"Tokens: {tokens}")
# 语法分析
parser = Parser(tokens)
ast = parser.parse()
print(f"AST: {repr(ast)}")
# 生成三地址码
generator = TACGenerator()
generator.generate(ast)
instructions = generator.get_instructions()
print("Generated TAC:")
for i, instr in enumerate(instructions):
print(f" {i+1}. {instr}")
# 测试案例
test_function("""
int add(int a, int b) {
return a + b;
}
int main() {
int x = 5;
int y = 3;
int z = add(x, y);
return z;
}
""")
test_function("""
int factorial(int n) {
if (n <= 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main() {
int result = factorial(5);
return result;
}
""")步骤 6:运行结果分析
运行上面的测试代码,我们会得到以下输出:
Testing code:
int add(int a, int b) {
return a + b;
}
int main() {
int x = 5;
int y = 3;
int z = add(x, y);
return z;
}
Tokens: [('int', 'int'), ('add', 'add'), ('(', '('), ('int', 'int'), ('a', 'a'), (',', ','), ('int', 'int'), ('b', 'b'), (')', ')'), ('{', '{'), ('return', 'return'), ('a', 'a'), ('+', '+'), ('b', 'b'), (';', ';'), ('}', '}'), ('int', 'int'), ('main', 'main'), ('(', '('), (')', ')'), ('{', '{'), ('int', 'int'), ('x', 'x'), ('=', '='), ('5', '5'), (';', ';'), ('int', 'int'), ('y', 'y'), ('=', '='), ('3', '3'), (';', ';'), ('int', 'int'), ('z', 'z'), ('=', '='), ('add', 'add'), ('(', '('), ('x', 'x'), (',', ','), ('y', 'y'), (')', ')'), (';', ';'), ('return', 'return'), ('z', 'z'), (';', ';'), ('}', '}')]
AST: Sequence([FunctionDefinition('add', [('int', 'a'), ('int', 'b')], 'int', ReturnStatement(BinaryOp('+', Variable('a'), Variable('b')))), FunctionDefinition('main', [], 'int', Sequence([Assignment(Variable('x'), Constant(5)), Assignment(Variable('y'), Constant(3)), Assignment(Variable('z'), FunctionCall('add', [Variable('x'), Variable('y')])), ReturnStatement(Variable('z'))]))])
Generated TAC:
1. add:
2. push ebp
3. mov ebp, esp
4. a = [ebp + 8]
5. b = [ebp + 12]
6. t0 = a + b
7. return t0
8. mov esp, ebp
9. pop ebp
10. ret
11. main:
12. push ebp
13. mov ebp, esp
14. x = 5
15. y = 3
16. push y
17. push x
18. call add
19. add esp, 8
20. t1 = eax
21. z = t1
22. return z
23. mov esp, ebp
24. pop ebp
25. ret
Testing code:
int factorial(int n) {
if (n <= 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main() {
int result = factorial(5);
return result;
}
Tokens: [('int', 'int'), ('factorial', 'factorial'), ('(', '('), ('int', 'int'), ('n', 'n'), (')', ')'), ('{', '{'), ('if', 'if'), ('(', '('), ('n', 'n'), ('<=', '<='), ('1', '1'), (')', ')'), ('{', '{'), ('return', 'return'), ('1', '1'), (';', ';'), ('}', '}'), ('else', 'else'), ('{', '{'), ('return', 'return'), ('n', 'n'), ('*', '*'), ('factorial', 'factorial'), ('(', '('), ('n', 'n'), ('-', '-'), ('1', '1'), (')', ')'), (';', ';'), ('}', '}'), ('}', '}'), ('int', 'int'), ('main', 'main'), ('(', '('), (')', ')'), ('{', '{'), ('int', 'int'), ('result', 'result'), ('=', '='), ('factorial', 'factorial'), ('(', '('), ('5', '5'), (')', ')'), (';', ';'), ('return', 'return'), ('result', 'result'), (';', ';'), ('}', '}')]
AST: Sequence([FunctionDefinition('factorial', [('int', 'n')], 'int', IfStatement(BinaryOp('<=', Variable('n'), Constant(1)), ReturnStatement(Constant(1)), ReturnStatement(BinaryOp('*', Variable('n'), FunctionCall('factorial', [BinaryOp('-', Variable('n'), Constant(1))])))), FunctionDefinition('main', [], 'int', Sequence([Assignment(Variable('result'), FunctionCall('factorial', [Constant(5)])), ReturnStatement(Variable('result'))]))])
Generated TAC:
1. factorial:
2. push ebp
3. mov ebp, esp
4. n = [ebp + 8]
5. t0 = n <= 1
6. iffalse t0 goto L0
7. return 1
8. goto L1
9. L0:
10. t1 = n - 1
11. push t1
12. call factorial
13. add esp, 4
14. t2 = eax
15. t3 = n * t2
16. return t3
17. L1:
18. mov esp, ebp
19. pop ebp
20. ret
21. main:
22. push ebp
23. mov ebp, esp
24. push 5
25. call factorial
26. add esp, 4
27. t4 = eax
28. result = t4
29. return result
30. mov esp, ebp
31. pop ebp
32. ret实用案例分析
案例:实现递归函数的中间代码生成
递归函数的中间代码生成与普通函数类似,但需要注意栈帧的管理。让我们通过一个更复杂的递归函数示例来演示:
# 测试递归函数
test_function("""
int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
int main() {
int result = fibonacci(5);
return result;
}
""")运行结果分析:
Testing code:
int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
int main() {
int result = fibonacci(5);
return result;
}
Tokens: [('int', 'int'), ('fibonacci', 'fibonacci'), ('(', '('), ('int', 'int'), ('n', 'n'), (')', ')'), ('{', '{'), ('if', 'if'), ('(', '('), ('n', 'n'), ('<=', '<='), ('1', '1'), (')', ')'), ('{', '{'), ('return', 'return'), ('n', 'n'), (';', ';'), ('}', '}'), ('else', 'else'), ('{', '{'), ('return', 'return'), ('fibonacci', 'fibonacci'), ('(', '('), ('n', 'n'), ('-', '-'), ('1', '1'), (')', ')'), ('+', '+'), ('fibonacci', 'fibonacci'), ('(', '('), ('n', 'n'), ('-', '-'), ('2', '2'), (')', ')'), (';', ';'), ('}', '}'), ('}', '}'), ('int', 'int'), ('main', 'main'), ('(', '('), (')', ')'), ('{', '{'), ('int', 'int'), ('result', 'result'), ('=', '='), ('fibonacci', 'fibonacci'), ('(', '('), ('5', '5'), (')', ')'), (';', ';'), ('return', 'return'), ('result', 'result'), (';', ';'), ('}', '}')]
AST: Sequence([FunctionDefinition('fibonacci', [('int', 'n')], 'int', IfStatement(BinaryOp('<=', Variable('n'), Constant(1)), ReturnStatement(Variable('n')), ReturnStatement(BinaryOp('+', FunctionCall('fibonacci', [BinaryOp('-', Variable('n'), Constant(1))]), FunctionCall('fibonacci', [BinaryOp('-', Variable('n'), Constant(2))])))), FunctionDefinition('main', [], 'int', Sequence([Assignment(Variable('result'), FunctionCall('fibonacci', [Constant(5)])), ReturnStatement(Variable('result'))]))])
Generated TAC:
1. fibonacci:
2. push ebp
3. mov ebp, esp
4. n = [ebp + 8]
5. t0 = n <= 1
6. iffalse t0 goto L0
7. return n
8. goto L1
9. L0:
10. t1 = n - 1
11. push t1
12. call fibonacci
13. add esp, 4
14. t2 = eax
15. t3 = n - 2
16. push t3
17. call fibonacci
18. add esp, 4
19. t4 = eax
20. t5 = t2 + t4
21. return t5
22. L1:
23. mov esp, ebp
24. pop ebp
25. ret
26. main:
27. push ebp
28. mov ebp, esp
29. push 5
30. call fibonacci
31. add esp, 4
32. t6 = eax
33. result = t6
34. return result
35. mov esp, ebp
36. pop ebp
37. ret总结
本集我们通过实战案例,详细讲解了如何为函数生成中间代码,重点关注了以下内容:
函数的中间代码表示:包括函数声明、定义和调用
栈帧布局:函数执行时在栈上分配的内存区域,用于存储返回地址、参数、局部变量等
参数传递方式:值传递、引用传递和寄存器传递
函数调用的三地址码生成规则:计算实参、传递参数、调用函数、获取返回值
函数定义的三地址码生成规则:序言、参数处理、函数体、尾声
递归函数的中间代码生成:与普通函数类似,但需要注意栈帧的管理
通过本集的学习,我们掌握了函数的中间代码生成技术,完成了中间代码生成篇的实战部分。在下一集中,我们将开始学习中间代码优化的基础知识。