嵌入式程序调用函数的内部过程和机制
在嵌入式程序中,当一个函数调用发生时,它的内部机理是什么,执行了哪些步骤?如下所示是一个程序在运行时,它的内存分布状况。
当一个程序开始运行时,它的代码被装入到内存,保存在代码区,包括主函数和其他函数的代码。另外,还有三块内存区域用来存放数据。第一块是全局变量区域,存放了程序当中的所有全局变量。由于全局变量的个数和大小是已知的,所以这一块区域所占用的内存大小在开始时即可确定下来,它们被称为是静态分配。位于此区域内的变量,它们在程序的整个运行过程当中,都一直存在,只有当整个程序运行结束了, 这一块内存区域才会被释放。第二块区域是栈(stack)区域,它包含了所有的栈帧。所谓的栈帧( stack frame),就是在调用一个函数时,系统会自动地分配一块内存区域给这个函数,用来保存它的运行上下文、形参和局部变量等信息,这样的一块内存区域,就叫做一个栈帧。栈帧是在函数调用时分配的,当函数调用结束之后,相应的栈帧就会被释放。所以,对于一个函数的局部变量来说,只有当函数调用发生时,系统才会给这个函数的形参和局部变量分配存储空间;当函数调用结束后,这些局部变量就被释放掉了。另外,由于栈区域是由系统自动来分配的,用户并不需要去关心,所以也称为是自动分配。第三块区域是堆(heap) 区域,它主要是用作动态分配的内存。
如上图所示是函数调用的一个例子,它考察的是最简单的一种情形,即在整个程序当中,只有一个main函数。在这种情况下,当程序开始运行时,它就会被装入到内存。它的代码存放在内存的代码区域。由于在这个程序中定义了一个全局变量z,所以就在内存的全局变量区域分配了一个存储单元给它,并且把它初始化为0。接下来,系统就要调用主函数main去运行了,当这个函数调用发生时,系统就会在栈中给它分配一块内存空间,即一个栈帧,用来存放主函数当中所定义的局部变量,即x和y。随后,程序计数器PC就跳转到主函数的第一条语句, 开始执行。当main函数执行完后,首先要把它所占用的栈帧释放掉。对于任何一次函数调用来说,在函数调用结束后,都要把相应的栈帧释放掉,所以x和y这两个局部变量所占用的存储空间就被释放掉了,不能再访问了。接下来,由于main函数是一个特殊的函数,当它执行完之后,整个程序也就结束了。
当一次函数调用发生时,它的执行过程可以归纳为以下5个步骤:
-
在内存的栈空间当中为其分配一个栈帧,用来存放该函数的形参变量和局部变量。
-
把实参变量的值复制到相应的形参变量中。
-
控制流转移到该函数的起始位置。
-
该函数开始执行。
-
当这个函数执行完以后,控制流和返回值返回到函数调用点。
如下图所示是变量的存储与作用域的一个例子。
关注公众号,发送关键字:Java车牌识别,获取项目源码。