算数表达式

例子: 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 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指令会对两个寄存器进行对应的操作,然后设置标志位
1

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:

while 语句

for 语句

 posted on 2025-02-24 18:16  Dylaris  阅读(67)  评论(0)    收藏  举报