-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathREADME.txt
83 lines (54 loc) · 3.08 KB
/
README.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
*代码生成基本概念:
·代码生成器:将优化后的三地址码转化为目标码的翻译程序
·目标码的三种形式:
-- 绝对指令代码:能够立即执行的二进制代码,所有地址已经定位
-- 可重新定位指令代码:待装配的机器语言模块,执行时由链接器把他们和某些程序连接起来,转换为可执行的二进制机器语言代码
-- 汇编指令代码:尚未经过汇编器汇编成二进制的汇编代码
·代码生成主要考虑的问题:
-- 如何使生成目标代码较短
-- 如何充分利用寄存器,减少目标代码中访问存储单元次数
-- 如何充分利用不同cpu指令系统的特点
·代码生成器的主要任务:
-- 指令选择:代码生成器将中间码转换成目标机器码。一个中间码可以有多种机器码转换,所以代码生成器负责选择指令。
-- 寄存器申请:程序执行过程中可能需要保存一系列值。目标机器架构可能不允许所有的值都保存在CPU内存或寄存器。代码生成器决定寄存器保存哪些值。同样,也决定寄存器保存哪些值。
-- 指令顺序:一个代码生成器决定指令执行的顺序,它创建指令调度来执行它。
·一个目标原型非常复杂,我们不可能描述出全部细节,所以我们通常会将其简化为一个简单目标机原型。
·一个简单目标机原型:
-- 加载、保存、运算、跳转等操作
-- 内存按字节、寄存器、指针指向寻址或其他间接寻址
-- n个通用寄存器R0,R1,....,Rn-1
-- 所以运算分量都是整数
-- 指令之间可能有一个标号
·寄存器:
-- TOP:存放作用域的基址
-- ZF:零标志ZF(Zero Flag)用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
·目标通常一个机器指令有几十上百个指令,为了简化通常只选取一些典型指令:
-- 加载指令:LD r, x
-- 保存指令:ST x,r
-- 运算指令:OP dst,src1,src2
SUB R1,R1,R2 // R1=R1-R2
-- 无条件跳转指令:BR L
-- 条件跳转指令:Bcond r,L
-- 压栈操作指令:
push #1 将数字1压栈
push TOP 将寄存器TOP压栈
push @sp 将指针sp指向的值压栈
-- 移动指令:
MOVE R0,R1 将寄存器R0的值移入到R1中
MOVE #1 R0 将数字1移入寄存器R0中
MOVE #1 @TOP 将数字1移到寄存器指向的位置
MOVE #1 @(TOP+4) 将数字1移到寄存器指向的位置基础上再加4位的位置
-- 比较指令:CMP R0,R1 比较两个寄存器中值的大小
-- 代码段行号跳转:JMP @(TOP-8)
·运算语句的三地址转目标代码:
三地址码:
x=y-z
目标代码:
LD R1,y //R1=Y
LD R2,z //R2=Z
SUB R1,R1,R2 //R1=R1-R2
ST X,R1 //X=R1
解析:优秀的代码生成器应该避免使用上面的全部4个指令,如果:
①所需的分量已经在寄存器中了
②运算结果不需要存放内存