哪一个是初始堆栈指针的正确值?

时间:2015-10-22 10:17:13

标签: c gcc initialization stack arm

我正在使用ARM-GCC编译器,我在Internet上找到了两个版本的startup_stm32f10x_cl.c文件(启动代码)。处理器为:STM32F105RC(ARM Cortex M3)。

共同部分:

#define STACK_SIZE       0x100 /*!< The Stack size */
__attribute__ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];    

然后,第一个版本启动矢量表,如下所示:

void (* const g_pfnVectors[])(void) =
{       
  (void *)&pulStack[STACK_SIZE],     /*!< The initial stack pointer           */
  Reset_Handler,                /*!< Reset Handler                            */
...

而第二个版本看起来像这样:

void (* const g_pfnVectors[])(void) =
{       
  (void *)&pulStack[STACK_SIZE - 1],     /*!< The initial stack pointer           */
  Reset_Handler,                /*!< Reset Handler                            */
    ...

所以,我的问题是:
哪一个是正确的堆栈指针初始化?

2 个答案:

答案 0 :(得分:5)

来自M3核心指令集的ARM文档:

  

PUSH使用SP寄存器中的值减去4作为最高值   记忆地址

  

完成后,PUSH更新SP寄存器以指向该位置   最低储值

所以,我的解释是SP的起点必须是最高地址的+4,即紧接在Stack数组边界之后的地址。 因此

  

(void *)&amp; pulStack [STACK_SIZE]

看起来正确,因为该地址(尽管不是数组的一部分)永远不会被使用。

答案 1 :(得分:1)

我的ARMv7-M架构参考手册的本地副本声明:

  

有13个通用32位寄存器,R0-R12和a   另外三个具有特殊名称和用法的32位寄存器   模型。

     
      
  • SP 堆栈指针,用作指向活动堆栈的指针。对于   使用限制请参阅第0页的使用0b1101作为寄存器说明符   A5-154。这是预设为重置时主堆栈的顶部。见   有关更多信息,请在第B1-623页注册SP。 SP有时候   简称R13。
  •   

重点补充。所以,后者似乎是正确的。演员void *似乎毫无意义。