算数表达式
例子: 2 + 3 * 5 - 8 / 3
AST的生成
需要注意运算符的优先级
- 递归下降解析 (递归层次越深,优先级越高)
- 普拉特解析 (运算符权重越大,优先级越高)
AST:
(expression)
|
(-)
/ \
/ \
(+) (/)
/ \ / \
2 (*) 8 3
/ \
3 5
TAC的生成
TAC:
t1 = 3 * 5
t1 = 2 + t1
t2 = 8 / 3
t1 = t1 - t2
ASM的生成
ASM:
; t1 = 3 * 5
movq $3, %r8
movq $5, %r9
imulq %r9, %r8 ; t1 store in %r8
; t1 = 2 + t1
movq $2, %r9
addq %r9, %r8 ; t1 store in %r8
; t2 = 8 / 3
movq $8, %r9
movq %3, %r10
movq %r9, %rax
cqo
idivq %r10
movq %rax, %r9 ; t2 store in %r9
; t1 = t1 - t2
subq %r9, %r8 ; t1 store in %r8
print 语句
例子: print 1 + 2 * 3;
AST的生成
AST:
(print statement)
|
(expression)
|
(+)
/ \
1 (*)
/ \
2 3
TAC的生成
TAC:
t1 = 2 * 3
t1 = t1 + 1
call print(t1) ; no return value
; t1 = call print(t1) ; return value store in t1
ASM的生成
ASM:
; t1 = 2 * 3
movq $2, %r8
movq $3, %r9
imulq %r9, %r8 ; t1 store in %r8
; t1 = t1 + 1
movq $1, %r9
addq %r9, %r8 ; t1 store in %r8
; print function, arg store in %rdi
print:
... ; some operation
leave
ret
; call print(t1)
movq %r8, %rdi
call print
全局变量
例子:
int var1;
int var2;
var1 = 5;
var2 = 1;
print var1 + var2;
重要的数据结构---符号表, 变量的声明无需生成对应的AST,修改符号表的内容即可
- 变量声明
- 变量赋值/存储值/读取值
AST的生成
AST:
(statements) (assign)
| / \
(glue) (expr) (lvident)
/ \
/ \
(glue) (print)
/ \
(assign) (assign)
说明:
通过glue(连接)节点把多个语句串联起来,对于assign(赋值)节点来说,我们要先计算右值,所以把他放在左子树,然后将结果赋值给左值(left value, lv)
TAC的生成
TAC:
t1 = 5
var1 = t1
t1 = 1
var2 = t1
t1 = var1 + var2
call print(t1)
ASM的生成
ASM:
; declaration
.comm var1, 8, 8
.comm var2, 8, 8
; t1 = 5
movq $5, %r8
; var1 = 5
movq %r8, var1(%rip)
; t1 = 1
movq $1, %r8
; var2 = t1
movq %r8, var2(%rip)
; t1 = var1 + var2
movq var1(%rip), %r8
addq var2(%rip), %r8 ; t1 store in %r8
; print function, arg store in %rdi
print:
... ; some operation
leave
ret
; call print(t1)
movq %r8, %rdi
call print
关系表达式
例子:
int x;
x = 7 < 9;
AST的生成
AST:
(assign)
/ \
(expr) (lvident) 注释: left value identifier
TAC的生成
TAC:
t1 = 7 < 9
x = t1
ASM的生成
ASM:
; declaration
.comm x, 8, 8
; t1 = 7 < 9
movq $7, %r8
movq $9, %r9
cmpq %r9, %8
setl %r9b
andq $255, %r9 ; t1 store in %r9
; x = t1
movq %r9, x(%rip)
cmpq指令会对两个寄存器进行对应的操作,然后设置标志位

sete setne setl setg setle setge 这6个指令可以根据标志位设置一个寄存器的 最低8位(一字节) 为1或0
if 语句
例子:
{
int i; int j;
i=6; j=12;
if (i < j) {
print i;
} else {
print j;
}
}
AST的生成
if AST:
(if statement)
/ | \
/ | \
/ | \
/ | \
/ | \
/ | \
condition true_body false_body
多个语句的AST:
stmt1; A_GLUE
stmt2; / \
stmt3; A_GLUE stmt4
stmt4; / \
A_GLUE stmt3
/ \
stmt1 stmt2
最终AST:
(glue)
/ \
(glue) (if statement)
/ \
(assign) (assign)
TAC的生成
TAC:
t1 = 6
i = t1
t1 = 12
j = t1
t1 = i < j
if_false t1 goto L_false
call print(i)
goto L_end
L_false:
call print(j)
L_end:
ASM的生成
; declaration
.comm i, 8, 8
.comm j, 8, 8
; t1 = 6
movq $6, %r8
; i = t1
movq %r8, i(%rip)
; t1 = 12
movq $12, %r8
; j = t1
movq %r8, j(%rip)
; t1 = i < j
movq i(%rip), %r8
movq j(%rip), %r9
cmpq %r9, %r8
jge L1 ; false case
; call print(i)
movq i(%rip), %r8
movq %r8, %rdi
call print
; goto L_end
jmp L2
L1:
; call print(j)
movq j(%rip), %r8
movq %r8, %rdi
call print
L2:
posted on
浙公网安备 33010602011771号