单片机开发中pc和sp的作用
概念
两个都是寄存器
pc(program counter)程序计数器
SP (stack pointer)堆栈指针
原理
pc 存放下一条指令的寄存器,cpu从内存中拿指令 ,寄存器是属于cpu的一部分,不属于内存
sp 堆栈指针,本质是寄存器,指向堆栈的顶部,
爬论坛:https://www.cnblogs.com/uestcliming666/p/11488782.html
假设有如下函数Fun
Fun()
{
…………………
Sub-fun(a, b);
…………………
}
cpu执行程序时的逻辑和步骤如下:
前提储备知识:
-
单片机对于堆栈的内存分配,一般栈空间由cpu自行分配,堆空间程序员可以用malloc进行申请,
-
栈空间一般储存非malloc分配的局部变量,全局变量和静态变量保s存在.date区域。一般对于函数内的局部变量,都保存在栈空间中,栈空间自动分配,自动释放,堆空间需要程序员自己free。
基于以上共识,开始对程序进行分析 -
执行CPU指令call,CPU会把目前PC寄存器的值push到stack 栈中,这个动作意味着存储返回地址。(很重要,要返回,向下)
-
cpu将参数a,b入栈,即根据CPU SP寄存器的值,把a、b的值存入SP指向的地址,并把SP减1(栈通常从高地址向低地址生长)。
注意是减一不是加一
-
cpu把pc寄存器的值指向子函数的地址,则下一个被执行的代码就是sub-fun的第一句
-
当函数sub-fun在执行时,可以根据目前SP寄存器的值计算出参数a、b的地址。
-
如果函数sub-fun有定义局部变量,这些变量的地址会从当前栈的顶端继续生长(这就是为什么我们在嵌入式开发时,总是会要求应用程序工程
不要定义size太大的局部变量,否则容易导致栈溢出的原因
)。 -
当函数sub-fun执行完毕后,CPU会执行ret指令,这个命令会从栈顶端pop出返回地址——即调用sub-fun之前Fun函数执行到的语句的地址,然后更改PC寄存器的值为这个返回地址,则下个指令就会返回执行函数sub-fun的下一行语句,从而完成了函数调用。
补充
-
堆栈和寄存器的关系,寄存器是内存吗
堆栈(Stack)和寄存器(Registers)是计算机体系结构中的两个不同的概念,它们在处理数据和控制程序流程方面扮演着不同的角色。 -
堆栈(Stack):
- 堆栈是计算机内存中的一部分,用于存储临时数据,如局部变量、函数参数、返回地址等。它遵循后进先出(LIFO)的原则,即最后推入(push)堆栈的数据会最先被弹出(pop)。
- 在函数调用时,当前函数的局部变量和参数会被推入调用者的堆栈帧(stack frame),当函数返回时,这些数据会被弹出,同时恢复调用者的程序计数器和栈指针。
-
寄存器(Registers):
- 寄存器是CPU内部的一组高速存储单元,用于存储指令、数据和地址等信息。寄存器的访问速度远远快于内存,因此它们被用来存储当前正在处理的数据和指令。
- 寄存器的种类很多,包括通用寄存器、浮点寄存器、指令指针寄存器(如程序计数器PC)、栈指针寄存器(如SP)和帧指针寄存器(如FP)等。其中,栈指针寄存器(SP)和帧指针寄存器(FP)与堆栈管理密切相关。
寄存器与内存的关系:
- 寄存器不是
内存
,它们是CPU的一部分,具有极快的访问速度。寄存器用于存储当前执行的指令和处理的数据,而内存(包括堆栈)则用于存储程序的代码、全局变量、静态数据以及在一定时间内不会被频繁访问的数据。
寄存器与堆栈的关系:
- 堆栈是内存的一部分,而寄存器(特别是栈指针寄存器SP)用于指向当前堆栈的顶部。当数据被推入堆栈时,SP寄存器的值会相应减少,指向新的堆栈顶部;当数据从堆栈弹出时,SP寄存器的值会增加,指向新的堆栈顶部。
- 在函数调用过程中,寄存器(如SP)和堆栈紧密协作,以确保函数的参数、局部变量和返回地址得到正确的管理。
总结来说,寄存器是CPU内部的高速存储单元,用于快速访问和处理数据;堆栈是内存的一部分,用于存储临时数据和控制信息。两者在程序执行过程中相互配合,但它们的功能和存储位置是不同的。