文章原稿
https://gitee.com/fakerlove/fundamentals-of-compiling

文章目录

  • 9. 运行时存储组织
    • 9.1 概述
    • 9.2 静态存储分配
    • 9.3 动态存储分配
      • 9.3.1 活动记录
      • 9.3.2 建造display区的规则
      • 9.3.3 运行时的地址计算

9. 运行时存储组织

9.1 概述

运行时的存储组织及管理是目标程序运行时所需要存储空间的组织与管理以及源程序中变量存储空间的分配

静态存储分配

编译阶段编译程序实现对存储空间的管理,和为源程序中的变量分配存储的方法。

条件:如果在编译时能够确定源程序中变量在运行时的数据空间大小,且运行时不改变

但并不是所有数据空间大小都能在编译过程中确定!

动态存储分配

在目标程序运行阶段目标程序实现对存储空间的组织与管理,和为源程序中的变量分配存储的方法。

特点:在目标程序运行时进行分配;编译时要生成进行动态分配的目标指令。

9.2 静态存储分配

(1)分配策略

由于每个变量所需空间的大小在编译时已知,因此可以用简单的方法给变量分配目标地址。

具体步骤:

  • 开辟一数据区。(首地址在加载时确定)
  • 按编译顺序给每个模块分配存储。
  • 在模块内部按顺序给模块的变量分配存储,一般用相对地址,所占数据区的大小由变量类型确定。
  • 目标地址填入变量的符号表中。

这种分配策略要求语言不允许指针或动态分配,不允许递归调用过程(如果递归调用,就相当于又多加了一个函数,又需要分配存储空间了)。典型的例子是Fortran77

(2)模块(fortran子程序)的完整数据区

子程序需要在数据区中保留返回地址,形参也要分配存储以存放相应的实参信息。编译时还要分配临时变量空间(用于存放表达式计算的中间结果等)

FORTRAN子程序的典型数据区:

9.3 动态存储分配

由于编译时还不能具体确定某些数据空间的大小,故对它们分配存储空间必须在程序运行时进行。这时,编译程序生成有关存储分配的目标代码实际上的分配要在目标程序运行时进行。这种分配方式称为动态存储分配。

对于分程序结构,而且允许递归调用的语言,常使用栈式动态存储分配,即使用一个类似于堆栈的“运行栈”来实现数据区的分配。

分配策略

整个数据区为一个堆栈

  1. 当进入一个过程时,在栈顶为其分配一个数据区。
  2. 当退出一个过程时,撤消该过程的数据区。

9.3.1 活动记录

一个典型的活动记录可以分为三部分:

(1)局部数据区:存放模块中定义的各个局部变量

(2)参数区:存放隐式参数(不出现在用户源程序中)和显式参数(出现在用户源程序中)。

形参数据区:每一形参都要分配数据空间,形参单元中存放实参值或者实参地址

prev abp:存放调用模块记录基地址。该函数执行完时,释放其数据区,数据区指针指向调用前的位置。

ret addr:返回地址,即调用语句的下一条执行指令地址

ret value :函数返回值(无值则空),比如void函数,就是空的。

(3)display区:存放各外层模块活动记录的基地址。

变量二元地址(BL、ON)

BL:变量声明所在的层次,可以用它找到该层数据区开始地址。此为嵌套层次,并列过程具有相同的层次。

ON:相对于显式参数区开始位置的位移(相对地址)。

例如:

程序模块1:

x(1,0) x在第一层中被声明,在显式参数区开始的位置是0;

y(1,1) NAME(1,2)

过程块M1:

IND(2,0) x(2,1)

注意⚠️:高层(内层)模块可以引用低层(外层) 模块中的变量,例如在M1中可引用外层模块中定义的变量 Y。
在 M1 中引用Y时,可通过其 display 区找到程序块 1 的活动记录基地址,加上 Y 在该数据区的相对地址就可以求得 y 的绝对地址,具体如何引用将在后面提到。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MdXrPZcg-1621079380807)(picture/20201121213704.png)]

以下是运行栈的跟踪情况:

因此可以画出完整的运行栈图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YzMqIf1-1621079380813)(picture/20201121214111.png)]

(e)当模块4执行完,则abp:=prev abp,这样abp恢复到进入模块4时情况,运行栈情况如©。

(f)当M2执行完,则abp:=prev abp,这样abp恢复到进入模块M2时情况,运行栈情况如(b)。

(g)当M1执行完,则abp:=prev abp,这样abp恢复到进入模块M1时情况,运行栈情况如(a)。

(h)当最外层模块执行完,运行栈恢复到进入模块时的情况,运行栈空。

9.3.2 建造display区的规则

从i层模块进入(调用)j层模块:

(1)若j=i+1

复制i层的display,然后增加一个指向i层模块记录基地址的指针

(第j层模块的display)

(2)若j<=i ,即调用外层模块或同层模块

将i层模块的display区中的前面第j-1个复制到第j层模块的display区

若发生了j>=i+2的情况,例如图中,i想要调用模块k

在这种情况是不行的,因为k的生命周期在j里面。当j执行完后到CALL k后,j(k的外层)生命周期已完结,不能直接调用k。

如果举一个特例的话,如果k中要调用j的变量,如果i直接调用k,那么k将会找不到来自外层的j的变量。

9.3.3 运行时的地址计算

假设要访问的变量的二元地址为:(BL,ON) ,要在LEV层模块中引用BL层模块定义的变量。

如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXUDUreR-1621079380821)(picture/20201121214054.png)]

在abp(3)引用IND(2,0),会将abp设为display(2),即abp(2),加上display区大小BL-1=1,再加上隐式参数区大小nip=2,与偏移量0,即使IND的地址。

编译原理教程_9 运行时存储组织相关推荐

  1. 编译原理--运行时存储组织(自己看)

    1. 存储分配的基本概念 1.过程:函数和过程的程序单员 2.过程的活动:程序的一次执行 3.活动记录:一块连续的存储空间,存储过程活动的执行代码和所需信息. 名字.环境.状态.存储单元.值的关系 解 ...

  2. GCC编译、链接、运行时库查找顺序(最真实可信)

    参考了不少资料,其中最靠谱是这个:http://www.mingw.org/wiki/librarypathhowto 和http://www.kaizou.org/2015/01/linux-lib ...

  3. KEIL5工程不能编译和下载,运行时提示找不到.axf文件(Error: Flash Download failed - Could not load file“.axf“)

    KEIL5工程不能编译和下载,运行时提示找不到.axf文件 KEIL5工程不能编译和下载,运行时提示找不到.axf文件 keil5debug运行时弹出警告 在网上找了好多办法都试过,就是不行,最终根据 ...

  4. ADO连接数据库,编译到客户机运行时出现CreateInstance报错0x80004002、CreateParameter报0xC0000005错误的解决方法。

    ADO连接数据库,编译到客户机运行时出现CreateInstance报错0x80004002,经查是由于ADO版本不一致引起的. 解决方法将原来stdafx.h中的 #import "c:\ ...

  5. 编译原理教程_1 引论

    文章下载地址-关注我的gitee https://gitee.com/fakerlove/fundamentals-of-compiling 文章目录 1. 引论 1.1 什么是编译原理 1.1.1 ...

  6. VS或VC编译正常,但运行时出现Stack overflow

    以下内容为网络资源结合自身实践的总结,在此首先感谢提供资源的各位网友. 大家都知道,Windows程序的内存机制大概是这样的,全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较大,一般 ...

  7. Java 内存管理、JVM 工作原理与 Java 运行时系统

    Java 虚拟机规范中说明:所有的对象实例(all class instances)以及数组都要在堆上分配: the heap is the runtime data area from which ...

  8. 编译原理实验二(全部存储到数组再逐行验证语法版.....这种思路被老师否了,应该是验证一行扔掉一行才对)

    编译原理实验二(可能还有BUG,不确定继续找) 要大改一次23333,老师的意思是不能用数组存储,而是一边识别单词,然后识别完一行就判断一次语法 写实验二的时候找到的实验一的一个逻辑错误 改动了实验一 ...

  9. .net报表控件ActiveReports教程:运行时修改数据(附源码)

    ActiveReports 是一款专注于 .NET 和 .NET Core 平台的报表控件.通过拖拽式报表设计器,可以快速地设计 Excel表格.Word文档.图表.数据过滤.数据钻取.精准套打等类型 ...

最新文章

  1. BZOJ-1644: [Usaco2007 Oct]Obstacle Course 障碍训练课(SPFA)
  2. SQLiteOpenHelper简介
  3. LeetCode 1128. 等价多米诺骨牌对的数量(哈希)
  4. mysql中文乱码 go_Mysql binlog乱码问题研究-Go语言中文社区
  5. python实现的、带GUI界面电影票房数据可视化程序
  6. 3d激光雷达开发(voxel滤波)
  7. Python接口自动化之cookie、session应用
  8. 左手代码,右手带娃,还能发十几篇 paper,程序员女神是如何炼成的?
  9. heartbeat双机热备配置(适用centos6\rhel6)
  10. 第3.1~3.3节《合成孔径雷达成像原理-皮亦鸣》
  11. python桌面爬虫_Python爬虫 利用python爬取ZOL桌面壁纸大图
  12. 国内外已知SAR卫星相关信息整理(持续更新-2022.9.6)
  13. 怎么修改照片大小?一键快速修改图片宽高尺寸的方法
  14. DTI数据TBSS组间统计对比设计矩阵
  15. List<Map,Object>>怎样取出map集合中的某一个的key值?
  16. Guitar Pro8电脑版更新下载及主要功能介绍
  17. 红楼梦java_蒋勋细说红楼梦——缘分告别时的淡淡哀伤
  18. 3d游戏建模行业发展前景和待遇怎么样?学习的渠道有哪些
  19. 手机有监控功能?分分钟查询手机使用记录!早点知道就好了!
  20. 1.8 监督学习应用

热门文章

  1. C++之禁用特定告警
  2. Ubuntu20.04更新源步骤
  3. vant在cell中加表格_在vant 中使用cell组件 定义图标该图片和位置操作
  4. 数据三等分离散python_plotnine:Python版的ggplot2包
  5. netperf网卡测速ubuntu linux 环境下测硬件网卡速度
  6. 微信小程序实现下拉刷新
  7. 漂流瓶html5,微信又搞事情?漂流瓶下线,居然还有这些新功能...
  8. python打印tensor_如何在TensorFlow中打印SparseTensor内容?
  9. 静态内部类实现单例_为什么用枚举类来实现单例模式越来越流行?
  10. vagrant 常用的几个命令