|
4 | 4 |   运行时刻跟编译时刻虽然是两个不同的阶段,但是由于运行时刻用到的指令是由编译器生成的,要使编译器生成正确指令,必需对程序运行时有足够的了解。
|
5 | 5 |
|
6 | 6 | ## 内容:
|
7 |
| - |
| 7 | +* 操作系统给内存进行规划,将内存大概分成操作系统内核内存和给程序员使用的内存2大部分,这样的好处是:操作系统的内存不会被大量占用,避免机器卡住、卡死、死机等状态,可通过操作系统把应用程序关闭,使得操作系统更安全。 |
| 8 | +* 内存空间之间是连续的 |
| 9 | +* 操作系统的内存具体规划,从低位到高位分别是: |
| 10 | + <br/> |
| 11 | + ~ 代码段:函数编译成opcode(二进制)后存到磁盘,运行时将二进制从磁盘加载到内存中。 |
| 12 | + <br/> |
| 13 | + ~ 数据段(静态空间):全局变量、常量、静态变量存数据段 |
| 14 | + <br/> |
| 15 | + ~ 堆:比栈内存大得多,一般有几G大小。 |
| 16 | + <br/> |
| 17 | + ~ 自由可分配内存: |
| 18 | + <br/> |
| 19 | + ~ 栈:第一个函数运行时压入栈底,函数调新函数时再往栈里压入该新函数,新函数运行完即出栈,第一个函数运行完再出栈,栈为空 |
| 20 | + <br/> |
| 21 | + ~ 系统内核:操作系统给内存进行规划,将内存大概分成操作系统内核内存和给程序员使用的内存2大部分,这样的好处是:操作系统的内存不会被大量占用,避免机器卡住、卡死、死机等状态,可通过操作系统把应用程序关闭,使得操作系统更安全。 |
| 22 | +* 关于程序调用的系统栈的分析:当函数A执行到第2行时,开始运行函数B,此时A停止开始运行B,并向系统栈中压入A2(表示函数A的第2行),当B执行到第2行时开始运行函数C,并在系统栈中压入B2,当C运行完时再查看系统栈,发现了B2,系统开始继续执行B的第2行,B执行完后查看系统栈,发现A2,则继续执行A直到完成。 |
| 23 | +* 符号表简介:编译器各种阶段都可能跟表格产生联系 |
| 24 | +* 符号表的作用: |
| 25 | + <br/> |
| 26 | + ~ 一致性检查:查符号表检查标示符是否为标号(label) |
| 27 | + <br/> |
| 28 | + ~ 作用域分析:同一个名字在不同函数嵌套中代表的地址不一样 |
| 29 | + <br/> |
| 30 | + ~ 辅助代码生成:为目标代码生成进行优化提供信息 |
| 31 | +* 符号表实例: |
| 32 | + ``` |
| 33 | + NAME INFORMATION |
| 34 | + index 整型,变量 |
| 35 | + socre 实型,变量 |
| 36 | + p 数组,形式参数 |
| 37 | + ``` |
| 38 | +* 常见符号表: |
| 39 | + <br/> |
| 40 | + ~ 名字表(nametab) |
| 41 | + <br/> |
| 42 | + ~ 程序体表(btab) |
| 43 | + <br/> |
| 44 | + ~ 层次显示表(display) |
| 45 | + <br/> |
| 46 | + ~ 数组信息表(atab) |
| 47 | + <br/> |
| 48 | + ~ 中间代码表(code) |
| 49 | +* 作用域分为:词法作用域和环境作用域(执行时作用域/动态作用域) |
| 50 | +* 词法作用域:在词法分析时就可以知道一个变量的作用域,如果是有一个作用域,则创建一个block,满足“最近嵌套原则”,并形成一个作用域链 |
| 51 | +* 词法闭包:在词法分析时就可以知道闭包的存在 |
| 52 | +* 执行环境:除了程序员自身写的代码外,程序自身会自带一个全局运行环境,例如js中在浏览器中的window对象,在node环境中的global对象 |
| 53 | +* 全局运行环境的组成: |
| 54 | + <br/> |
| 55 | + ~ hashmap:{} |
| 56 | + <br/> |
| 57 | + ~ level:0 //环境当前的嵌套层级,初始为0 |
| 58 | + <br/> |
| 59 | + ~ parent:sp //子环境(字作用域)指向父环境的指针 |
| 60 | +* 子作用域:js在调用函数时会创建一个子环境,并且,父环境对象作为一个参数传入这个子环境对象创建当中,这个子环境就是一个子作用域 |
| 61 | +* 三地址表达式实例2(斐波那契函数)栈的运行图示: |
| 62 | + ``` |
| 63 | + 栈空间(通过指针偏移拿到数据) 代码段空间(通过行号值拿到数据) |
| 64 | + | link7 | |
| 65 | + //link7会指向数字2 | f | |
| 66 | + | 2 | | t1=n==1 | |
| 67 | + | link6 | | t2=n==2 | |
| 68 | + | link5 | |t3=t1 or t2| |
| 69 | + |其他临时变量| | | |
| 70 | + | 返回值3 | |branch goto| |
| 71 | + | 3 | | ... | |
| 72 | + | link4 | | | |
| 73 | + | link3 | | | |
| 74 | + |其他临时变量| | | |
| 75 | + | 返回值2 | | | |
| 76 | + | 4 | | | |
| 77 | + | link2 | | | |
| 78 | + //link2会指向数字5 | | |
| 79 | + | link1 | | | |
| 80 | + //link1会指向代码call f | | |
| 81 | + |其他临时变量| | | |
| 82 | + | 返回值1 | | | |
| 83 | + //返回值可根据5的偏移量计算拿到 | call f | |
| 84 | + | 5 | //call f将指向第一行f |
| 85 | + ------------ -------------- |
| 86 | + ``` |
| 87 | +* 定义三地址码生成规则: |
| 88 | + <br/> |
| 89 | + ~ @:表示作用域 |
| 90 | + <br/> |
| 91 | + ~ set:赋值 |
| 92 | + <br/> |
| 93 | + ~ branch:if语句判断 |
| 94 | + <br/> |
| 95 | + ~ $:临时变量 |
| 96 | + <br/> |
| 97 | + ~ call:调用函数 |
| 98 | + <br/> |
| 99 | + ~ section:区块 |
| 100 | + <br/> |
| 101 | + ~ %:寄存器,%TOP%表示TOP寄存器 |
| 102 | + <br/> |
| 103 | + ~ SP:指针 |
| 104 | + <br/> |
| 105 | + ~ call:函数调用 |
| 106 | + <br/> |
| 107 | + ~ pass:表示传参 |
| 108 | +* 源码 → 三地址 |
| 109 | + ``` |
| 110 | + function fibonacci(n){ |
| 111 | + if(n==1 || n==2){ |
| 112 | + return n |
| 113 | + } |
| 114 | + return fibonacci(n-1)+fibonacci(n-2) |
| 115 | + } |
| 116 | + print(fibonacci(5)) |
| 117 | + ``` |
| 118 | + 转换后的三地址码: |
| 119 | + ``` |
| 120 | + section fibonacci@2 |
| 121 | + set %TOP% %SP% |
| 122 | + set $t1@2 n==1 |
| 123 | + set $t2@2 n==2 |
| 124 | + set $t3@2 $t1@2 || $t2@2 |
| 125 | + branch $t3@2 LB1 //$t3@2为true时继续,否则跳转到LB1行 |
| 126 | + return n@2 |
| 127 | + LB1:set $t4@2 n-1 |
| 128 | + pass $t4@2 //pass表示传参,压栈 |
| 129 | + call fibonacci@1 |
| 130 | + set $6@2 n-2 |
| 131 | + pass $t6@2 //pass表示传参,压栈 |
| 132 | + call fibonacci@1 |
| 133 | + set $t8@2 $t5@2 + $t7@2 |
| 134 | + return $t8@2@2 |
| 135 | + section main@1 |
| 136 | + set %TOP% %SP% |
| 137 | + declare function fibonacci@1 |
| 138 | + pass 5 |
| 139 | + call fibonacci@1 |
| 140 | + pass $t2@1 |
| 141 | + call print@1 |
| 142 | + ``` |
| 143 | +
|
0 commit comments