单片机全局变量 局部变量

2019-04-15 19:14发布


若在C51中定义一个全局变量,编译器将在RAM中为该变量指定一个专用地址,在C程序中给变量赋的值将存入这个专用地址中,程序操作该变量是,首先从专用地址中取出存放的值,然后再进行计算。全局变量被定义在内存中的专门地址上,存储位置固定。C51中定义一个的局部变量可以和全局变量同名,但在这种情况下,局部变量的优先级较高,而同名的全局变量在该功能模块内暂时被屏蔽。
若在C51中定义一个局部变量,编译器会将该变量的地址分配到寄存器组R0~R7中。由于他是局部变量,所以编译器将使用立即数赋值语句为代表该变量的寄存器Rn赋值,最后的计算结果也将存在寄存器组中,位置有编译器任意指定。局部变量由于用寄存器直接操作,存取速度和计算机速度都很快;由于寄存器数量有限,若局部变量过多,将会使代码由于频繁分配寄存器而变得冗长。
局部变量空间,就是堆栈空间,也就是栈空间。从局部变量声明的时候,它就在堆栈空间了,而不是调用函数的时候,才让它入栈的。定义一个局部变量a,编译器会将a的地址分配到寄存器组R0~R7中去。由于它是局部变量,所以编译器将使用立即数赋值语句为代表a的寄存器Rn赋值,最后计算的结果也将存在寄存器组中,位置由编译器任意指定。定义一个全局变量a,编译器将在RAM中为变量a指定一个专用地址,在C程序中给a赋的值将存入这个专用地址中。程序操作变量a时,首先从专用地址中取出存放的值,然后再进行计算。程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。

假如说在keil中定义了一个全局变量int i = 0x1234;这个i的初始化肯定是在上电之后,main函数之前。编译完之后debug,从地址0开始执行,怎么没看见对i的初始化呢?有的说是在init.a51文件之中。但是一直没有找到明确的解释。
代码都是烧写在ROM中的,而全局之类的变量都是在RAM中,所以上电的时候肯定要初始化的。我知道编译器肯定要在main之前加入初始化代码的,但是我不知道加在哪儿了?在keil 中debug后的汇编后的汇编中似乎看不见呢。一般来说,全局变量如果有初始值,它们会被存放在ROM的某个区域,上电后会执行一段从ROM到RAM复制的过程.....这就是全局变量的初始化.
你还记得用keil建工程的时候,有个提示:Copy Standard 8051 Startup Code to project folder and add file to project ?" 

这个提示就是说,是否添加Startup code 到工程 ,Startup code 是cpu复位或上电启动后立即运行的一段启动代码。
c编程的时候cpu先找到Startup code 代码,在跳到main函数入口  所以不是从rom 0地址开始的

而Startup code 代码的作用是:

1:清除片内外RAM PDATA  堆栈和指针
2:如果有全局变量,则初始化,如果无全局变量,则直接进入main函数在startup.a51后面的那句 LJMP ?C_START是关键,而 C_START是在init.a51中定义的,init.a51主要就是全局变量的初始化,然后init.a51又调用了main函数。

在http://www.keil.com/support/man/docs/c51/c51_ap_startup.htm上有说明
Startup code is executed immediately upon reset of the target system. The Keil startup code performs (optionally) the following operations in order:

Clears internal data memory
Clears external data memory
Clears paged external data memory
Initializes the small model reentrant stack and pointer
Initializes the large model reentrant stack and pointer
Initializes the compact model reentrant stack and pointer
Initializes the 8051 hardware stack pointer
Transfers control to code that initializes global variables or to the main C function if there are no initialized global variables