stack内存是函数调用的基础,在嵌入式系统开发时,系统程序要自行管理stack。如果管理不当,就可能发生一执行函数调用或函数调用多几层后就死机的状况,而且有许多系统不稳定现象或无厘头的bug ,都是因为stack使用不当所致的。首先要知道,c语言可利用stack内存完成下列事项。
1,function call时的返回地址记录。
2,function call时的参数传递。
3,函数内部的local变量也是使用stack存储。
4,TSR被执行时的CPU状态与返回地址
stack point 的设定与stack 内存的配置是一件很重要的事情,但很多人都疏忽了。
大多人都弄不清楚C语言的stack 和CPU的stack pointer 有什么关系,我简单地说一下吧。当用C语言调用了一个函数,并传入参数,例 如fun(a,b )编译后的机器码应包含以下动作;
1, 执行CPU指令“ push”将参数a,b存入stack;并把SP减1
2,执行CPU指令“call";CPU会把目前pc缓存器的值push到 stack中,这个动作意味着存储返回地址。
3,接着CPU把PC缓存器的值设为函数fun的地址,则下个被执行的指令就是函数fun的第一命令。
4,当函数fun在执行时,可以利用目前SP缓存器的值,计算出参数a与b的地址。
5,如果函数fun有定义局部变量,这些变量的地址会从目前stack 的顶端往下摆;这就是为什么我们在嵌入式系统开发时,总是会要求应用程序工程师不要定义size 太大的局部变量,否则很容易发生 stack overflow,
6,当函数fun执行完毕后,CPU会执行“tet”指令,这个命令会从stack顶层取出返回地址,然后更改PC缓存器的值为这个返回地址,则下个指令就会返回执行函数fun的下一行指令,从而完成函数调用。
以上的每一个动作几乎都与stack有关,如果SP缓存器没有设定正确的地址,或者没有配置足够大的内存当做stack ,那么程序中去调用函数时就很可能出问题。
至于stack的size就更难定义了简单地说就是在每一个function结束前读取SP缓存器的值,接着让测试人员操作所有的功能,最后会得出一个stack 曾被使用的最大值,把这个值再加一些buffeer,应该就是最合适的stack size了。 |