Loading

理解函数的调用过程 / pl0 语言

静态链和动态链

符号表的组织

pl0语言当中,符号表是全局的,动态变化的

增加符号

符号的属性

    • 其实是对应的基地址阶数
  • 相对偏移地址
    • 和通常意义上的栈区内存分配异曲同工

删除符号

不做内存处理,直接退回符号栈栈顶指针

函数

函数是如何被调用的

函数当中包含函数的逻辑,以及局部变量

深入理解计算机系统(3.7)------过程(函数的调用原理)

机器用栈来传递过程参数存储返回信息

允许嵌套定义的函数如何访问外部变量

  1. 根据 lev_def找到基地址
  2. 根据给定的 offset进行栈偏移寻址,得到变量

pl0语言当中层差的作用

外层不能访问内层的变量

😂人不可貌相

⭐根本原因:被调用函数并不知道调用者是谁

The callee doesn’t know who calls it😂

但是在创建栈帧的时候,我们可以指定一个

比如

main / 0

var a1,b1;

p / 1

var a2,b2;

q / 2

var a3,b3;

r1 / 3

r2 / 3

r 的过程体 / 4

var c1,d1,e1,f1;

s / 1

var c2,d2,e2,f2;

t / 2

var c3,d3,e3,f3;

u / 3

u 的过程体 / 4

【main 函数体】


首先需要明确

lev = k 的函数必须在 lev >= k过程当中调用

任意内层直接外层

比如 main调用 p

因为main 虽然在 lev0,但是main 的过程体在lev1,而p的定义lev1(p的过程体在lev2)


当r 的过程体(lev = 4)调用p(lev = 1) 时

会产生如下的cal指令

cal 3(lev_dif),offset(p)(base1)

当t 的过程体(lev = 3)调用p(lev = 1) 时

cal 2(lev_def),offset(p)(base1)

两个指令当中,p的新栈帧的静态链都会指向main

👇和base函数有关

base 函数

case cal: /* 调用子过程 */
    // ^ 静态链,指向定义过程中的直接过程,用于访问变量
    s[s_top] = base(cur_instr.lev_dif, s, stack_base);
    // ^ 动态链,指向调用者的基地址
    s[s_top + 1] = stack_base;
    // ^ 存储PC
    s[s_top + 2] = instr_ptr; /* 将当前指令指针入栈 */
    // instr_base = base(i.lev_dif, s, instr_base);
    stack_base = s_top;           /* 改变基地址指针值为新过程的基地址 */
    instr_ptr = (int)cur_instr.a; /* 跳转 */
    break;

base 函数如下

int base(int lev_dif, double *s, int stack_base)
{
    int b1;
    b1 = stack_base;
    while (lev_dif > 0)
    {
        b1 = s[b1];
        lev_dif--;
    }
    return b1;
}

r 的过程体当中调用p 时,栈帧的分布是

main->p->q->r->p

调用p 的时候,会沿着r 栈帧的基地址开始,回溯 2 步(层差 = 2)

过程是

lev_dif = 3; b = r栈帧底部;r 栈帧底部指向了r的调用者 q 的帧底
lev_dif = 2; b = q栈帧底部;q 栈帧底部指向了q的调用者 p 的帧底
lev_dif = 1; b = p栈帧底部;p 栈帧底部指向了p的调用者 main 的帧底
lev_dif = 0; done;

同样的offset,只是层差不同,不同父过程调用区别在哪里呢?

层差出现在 lod,sto,cal这三个原生命令的执行过程当中

在 pl0语言当中,符号表是随时变化的

访问本栈帧的变量当然没有问题,但是如何访问外部变量呢?

其本质目的是内层(高层)函数想要访问外层变量时,需要找到合适的基地址,才能根据偏移量找到实际的栈地址,取出变量

层差就是需要沿着静态链回溯的阶数

所有变量都封装在当前层数栈帧之上,需要得到栈帧基地址(%ebp)

⭐⭐⭐静态​链的作用:指向定义该过程的直接外过程的最新活动记录的栈帧基地址

  1. 定义
  2. 最新活动记录
  3. 基地址

为什么在C 语言当中我们不常看到 层差这个概念?

C 语言不允许函数嵌套定义,因此仅有局部变量$fp偏移)和全局变量.data),并不存在需要变换基地址访问的情况

ref

深入理解计算机系统(3.7)------过程(函数的调用原理)

posted @ 2020-11-06 20:44  ZXYFrank  阅读(677)  评论(0编辑  收藏  举报