<编译器> 6. 活动记录 | 1. 栈帧

 
tips

 
栈指针
帧指针
 
Frame 模块: 栈帧相关信息
 
F_frame             :    栈帧
F_access           :    表示 寄存器 / 栈帧 的地址偏移, 即位置
Symbol Temp_label        :    标识    
 
F_newFrame(label, boolList)    :    生成 符号 label 对应的新栈帧
F_formals()        :    返回形参的 access
F_allocLocal()    :    返回局部变量的 access
 
Translate 模块: 关联 栈帧 和 语义分析 , 相比 F_access, 添加了  level  信息
Tr_access                :    函数层 (标识嵌套信息) 与 栈帧信息 F_frame { Tr_level, F_access}
Tr_level                    :    嵌套层, 函数嵌套关系
 
Tr_allocLocal()         :    带 level 信息的局部变量 Tr_access 
Tr_formals()             :    带 level 信息的形参 Tr_access 
Tr_newLevel()          :    创建新的函数层  
 
Tr_newLevel(
    level_包围层,  ( 函数 f 的包围层, 即调用者 )
    f_当前层函数, 
    [ 标记形参是否逃逸的 Bool 数组 (第一个元素对应静态链)]
)
Tr_outermost()    :    最外层函数标识
 
transDec()
transExp()
transVar()
 
LIFO:  递归函数调用   ->    存储 
高阶函数:  支持递归调用, 支持以函数做为返回值, 不能用简单的 栈来存储,(在15章讨论)
 
栈 + 栈指针:
指针右侧: 垃圾回收
指针左侧: local 变量
活动记录: activity record ,  栈帧: stack frame
标准结构 :   可以实现 跨语言调用
栈地址    :   从高到低
 
栈帧  Stack Frames

 
 
 
帧指针  Frame Pointer & 栈指针 Stack Pointer 

 
Stack Frame:  栈帧
SP:    Stack Pointer    栈指针
FP:    Frame Pointer    帧指针
f( ... ) {
   ...
   g(x,y,....)
   ...
}

 

 
执行 函数 f()时,栈指针SP 在位置A, 
执行到  g(x,y,... )时发现要调用函数 g, 则SP -= FRAME_SIZE,   新的FP指向 SP 的地址。
新 FP ~ 新SP 的 FRAME_SIZE 个地址则保存调用过程中的所有数据, 以备后来之用。
 
参数传递
前 k 个放在寄存器中  (一般中 k=4 或 k=6)
 
f(g()):
临时变量 x 在函数 f() 调用以后不再需要: 放入一个调用者保护的寄存器中, 调用 g() 时不保护它
局部变量 i (f()内部)在函数 g( ) 调用前后都需要: f() 入口 放入被 调用保护 寄存器 ri 一次 , f()出口取回一次
 
 返回地址

call 指令地址 + 1   =>  放入 寄存器   =>  非叶过程 后面还有指令要跑, 所有结束后 还要等, 需要把地址存在自己的栈帧里面
 
 寄存器 or 栈帧 ?

 
寄存器中:
参数:寄存器中
返回地址:寄存器中
函数结果:寄存器中 返回
局部变量,中间结果:寄存器中
 
栈帧(存储)中:
    1.  传址变量:变量为一地址  ( &p )
    2.  该变量被嵌套在当前过程(函数)内的过程(其他函数)访问
    3.  变量值太大,不能放在单个寄存器中 ( 32位,4字节 或 64位, 8字节 )
    4.  变量是一个数组,元素需要地址运算(C语言)
    5.  需要使用存放该变量的寄存器
    6.  太多局部变量 临时变量, 无法全部放入寄存器中
    7.  函数参数大于k个 (k一般为 4 到 5个)
 
 
 
posted @ 2024-03-15 19:39  Leon大帝  阅读(6)  评论(0编辑  收藏  举报