鸡仔单片机成长记----------------浅谈51堆栈操作

  • 单片机
  • 辰__逸
  • LV3工程师
  • |      2016-09-08 20:29:43
  • 浏览量 765
  • 回复:2
本帖最后由 辰__逸 于 2016-9-8 20:43 编辑 今天来谈一下51的堆栈操作,堆栈是什么?堆栈是单片机在片内数据存储器中用与存储临时数据的区域,以SP来确定位置,8位寄存器,复位的时候值位07H。可以用MOV SP,#data来改变值。 用GCC来编译C语言中堆栈的操作与用KEIL中C程序对堆栈的操作不一样,下面先来说一下GCC编译中堆栈的操作:--------------------------------------- GCC中函数调用过程---------------------------------------------- 1>保存断点地址,即PC的值入栈,并且将PC的值赋值为要执行函数的地址,实际上是用LCALL实现的。 2>实际参数入栈。 3>为被调用函数分配存储空间。 4>被调函数从栈中取得参数,并开始执行函数体。(通过计算SP的值来计算出参数的地址) 5>被调函数执行结束前(return前),先将返回值入栈,函数执行结束,空间收回。 6>主调函数从栈中获得返回值。 7>主调函数从栈中获得断点地址。并从断点处继续运行(在这里读一下SP的值,栈空间的大小也就能估算了) 注意:每种编译器的处理方式都有些许差别,但是总的流程大体一致。 有些CPU的编译器在参数少的时候且参数类型简单时,会用CPU的寄存器来传递参数,但碰到参数比较多或者类型复杂的状况时,一定是用stack来传参数。----------------------------------------Cx51编译器中函数调用-------------------------------------------- 1>Cx51为每个参数分配一个特殊的地址 2>函数被调用时,调用者在传递控制权之前必须拷贝参数到分配好的存储区,函数就可以在从固定的存储区提取参数,在这个过程中,只有返回地址保存在堆栈中,中断函数要更多的空间,因为要保存一些寄存器的值 3>函数调用之后,出栈PC。调用者继续运行。 注意:在缺省条件下,Cx51最多可以用寄存器传递3个参数,若无寄存器可用,则用固定地址存放。CPU寄存器经常用来返回函数的返回值。把局部变量分配到固定的内存位置或者寄存器中,而不是堆栈中。还可能把不同函数的局部变量分到同一位置,这些都是以节约RAM为目的的。------------------------------------------------实例分析-------------------------------------------------------#include void delay(bit b,unsigned char a) //void delay(unsigned char a,bit b) { } void main() { while(1) { delay(1,50); // delay(50,1); } } 将上面的程序在KEIL中调试,并观察汇编代码,如下图: 这里的函数先传递参数是位类型的,放在位可寻址区里,第二个参数放在了固定地址里。也没有用寄存器传递参数啊!!!!!!这是什么鬼,让我们在看一张图: 这里我们可以清晰的看到了,第一个参数放在R7中了,而第二个还是在位可寻址区里面。 别着急,让我们在看一张图: 别急,在来一张: 聪明的人从图中就能看出端倪来了,让我来依次说明下: 1>从第一和第二张图我们可以看到,如果有参数是bit型的,则传递的时候最好是放在最后面,因为如果第一个参数是bit型的,Cx51就不会把剩下的参数用寄存器去传递,而是放在RAM的特定地址中。 2>Cx51最多只能用3个寄存器来传递参数,如果参数个数大于3个,剩下的就只能放在RAM的特定地址中了。 接下来看一下中断的处理: 从图上可以看出来:在进入中断有PUSH操作,在退出中断的时候有POP操作,这就是所谓的保护现场,而且SP的值也变了,这就是入栈和出栈的过程了。从图中我们还可以看到,堆栈是从高地址向低地址生长的。 今天就到这里了。我这里有关于KEIL的编译文档,现在不在身边,等有时间我传上来吧。
  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:2
灵澈 2016-09-09
分析的很到位
0   回复
举报
发布
kk118a 2016-09-08
楼主分析的不错,学习了
0   回复
举报
发布
x
收藏成功!点击 我的收藏 查看收藏的全部帖子