Skip to content

Latest commit

 

History

History

05_目标代码生成

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 


*代码生成基本概念:
·代码生成器:将优化后的三地址码转化为目标码的翻译程序
·目标码的三种形式:
  -- 绝对指令代码:能够立即执行的二进制代码,所有地址已经定位
  -- 可重新定位指令代码:待装配的机器语言模块,执行时由链接器把他们和某些程序连接起来,转换为可执行的二进制机器语言代码
  -- 汇编指令代码:尚未经过汇编器汇编成二进制的汇编代码
·代码生成主要考虑的问题:
  -- 如何使生成目标代码较短
  -- 如何充分利用寄存器,减少目标代码中访问存储单元次数
  -- 如何充分利用不同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个指令,如果:
    ①所需的分量已经在寄存器中了
    ②运算结果不需要存放内存