报头中的偏移量作用_C语言中函数的实现
符号表
C编译器使用符号表来记录程序中遇到的变量,类似汇编器中的label表,不过C编译器中的符号表包括更多信息:名字、类型、已分配的内存地址、变量申明域或作用域等
e.g 程序中有6个变量声明,编译器会生成6个表项的符号表,采用偏移量的方式记录变量在内存中的位置编译器的符号表变量的空间分配
存放变量内容的内存有两种区段:全局数据段(global data section)和运行时栈(run-time stack)。全局数据段是内存中存放全局变量的区段,即所有静态变量所在的地方;运行时栈则是局部变量所在的地方。
在LC-3体系计算机中,R4是一个专用寄存器,存放的是全局数据段的基地址,所以R4可以被看做成一个全局指针。
e.g 全局变量earth偏移量为4,将earth的内容读入寄存器R3,LC-3指令如下:LDR R3, R4, #4局部变量就会存放在一个被称作”活动记录“(activation record)或者”堆栈帧“(stack frame)的内存模板(memory template)中。活动记录就是一段连续的内存,包含了当前函数中所有的局部变量。每个函数都有自己的活动记录,当我们调用一个函数的时候,该函数活动记录的最大地址存放在寄存器R5中,R5被称为帧指针(frame pointer)。注意,在活动记录中,变量的排放顺序与他们在程序中的声明顺序是相反的。
e.g 变量amount在程序中是最先被声明的变量,它也是距离帧指针R5最近的变量,访问变量seconds,LC-3指令如下:LDR R0, R5, #-5LC-3内存中的一个活动记录当我们调用一个函数的时候,该函数的活动记录被压入当前栈,同时R5内容被调整,指向当前栈顶,当该函数结束的时候,控制权被交还给调用者,活动记录将被弹出当前栈,同时R5的内容也将被修改,指向调用者活动记录所在位置。整个过程中,寄存器R6始终指向运行时栈的顶部,R6为栈指针。
C语言中,函数调用包括三个步骤:
运行时栈
在函数被调用时,我们需要激活被调用函数,也就是说在函数被执行前,必须要在内存中,为该函数的局部变量分配空间。
每个函数的活动记录,在其每次被调用的时候,都会被系统在内存中分配一个活动记录空间。函数返回的时候,则将该活动记录返还,以供其他函数调用使用,这样是允许函数的递归操作的。其中采用数据结构”栈“来跟踪函数调用模式。
e.g
int main() { int a; int b;: b = Watt(a); b = Volta(a,b); }int Watt(int a) { int w;: w = Volta(w, 10); return w; }int Volta(int q; int r) { int k; int m;: return k; }上图是栈在代码运行的不同时刻的快照,每个阴影区代表一个特定函数的活动记录,将数据项压入栈时,栈顶总是向着低的内存地址方向移动。其中R5总是指向当前活动记录的某个地址(局部变量的起始地址),R6总是指向运行时栈顶。
实现机制
e.g
w = Volta(w, 10);1、调用
通过将两个参数值压入运行时栈,向Volta传递参数,R6指向运行时栈顶部,每当向栈中压入一个数据项,首先递减R6值,然后将数据存入R6指向的地址。在LC-3结构中,C函数的参数,按照它们在函数调用的顺序,从右到左依次被压入栈。
通过JSR指令,把控制权交给Volta
AND R0, R0, #0 ADD R0, R0, #10 ADD R6, R6, #-1 STR R0, R6, #0 LDR R0, R5, #0 ADD R6, R6, #-1 STR R0, R6, #0 JSR Volta2、被调用函数的开始
被调用函数的初始代码,要完成与调用信息相关的备份操作:
为返回值预留一个内存位置,通过栈指针递减,将一个内存空间“压”入栈,在被调用函数返回调用者之前,将返回值填入此内存。
调用者相关的信息的保存,即R7中调用者的返回地址和R5中调用者的帧指针(动态链)。
被调用者调整R6的值,在栈空间中为它的局部变量分配足够的空间,同时设置R5指向这些局部变量的基地址。
Volta: ADD R6, R6, #-1 ADD R6, R6, #-1 STR R7, R6, #0 ADD R6, R6, #-1 STR R5, R6, #0 ADD R5, R6, #-1 ADD R6, R6, #-23、被调用函数的结束
如果存在返回值,则填写活动记录的返回值字段。
将局部变量弹出栈
恢复原动态链的内容
恢复返回地址
通过RET指令,返回调用者
LDR R0, R5, #0 STR R0, R5, #3 ADD R6, R5, #1 LDR R5, R6, #0 ADD R6, R6, #1 LDR R7, R6, #0 ADD R6, R6, #1 RET4、返回调用函数
将返回值(如果有)出栈
参数出栈
JSR Volta LDR R0, R6, #0 STR R0, R5, #0 ; w = Volta(w, 10); ADD R6, R6, #1 ADD R6, R6, #2总结
以上是生活随笔为你收集整理的报头中的偏移量作用_C语言中函数的实现的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Weblogic 所有BEA错误代码详细
- 下一篇: 临时手机验证码_实用网站(一)短信验证码