首页 > 其他 > 详细

为什么 __start 是处理器执行的第一条指令?

时间:2014-04-13 03:46:57      阅读:684      评论:0      收藏:0      [点我收藏+]
(rtos nuttx 7.1 stm32 源代码分析)

为什么 __start 是处理器执行的第一条指令?

转载请注明出处:http://blog.csdn.net/zhumaill/article/details/23426605

在《NuttX 启动流程》一文中提到, __start 是处理器执行的第一条指令。那么,为什么在 NuttX 中 __start 是处理器执行的第一条指令?为什么我要把 __start 称为“处理器执行的第一条指令”,而不是称为“程序入口点”?

nuttx/configs/shenzhou/scripts/ld.script:
......
OUTPUT_ARCH(arm)
ENTRY(_stext)
SECTIONS
......
这里的 ENTRY(_stext) 定义的程序入口点是 _stext。

nuttx/arch/arm/src/Makefile:
......
nuttx$(EXEEXT): $(HEAD_OBJ) board/libboard$(LIBEXT)
    $(Q) echo "LD: nuttx"
    $(Q) $(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) $(EXTRA_LIBPATHS)         -o $(NUTTX) $(HEAD_OBJ) $(EXTRA_OBJS)         --start-group $(LDLIBS) $(EXTRA_LIBS) $(LIBGCC) --end-group
......
这里的 --entry=__start 在链接时重新指定了程序入口点为 __start。
xxx@xxx-desktop ~ $ readelf -h nuttx
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2‘s complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x80003d1
  Start of program headers:          52 (bytes into file)
  Start of section headers:          145184 (bytes into file)
  Flags:                             0x5000202, has entry point, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         18
  Section header string table index: 15
在编译生成的 elf 文件 nuttx 的文件头中可以找到这个程序入口点的地址0x80003d1。

但是,这个程序入口点只对 elf 格式的文件有用,在非 elf 格式的祼机程序中,这个程序入口点不起作用,我们烧写到芯片 flash 中的格式为 .bin 或 .hex 的文件中没有这个程序入口点的定义。把这里的 __start 改成其它函数一样可以正常运行。

根据 cortex-m3 的定义,系统从 flash 启动时,0x08000004中的值就是 PC(程序计数器)的初始值,这才是真正起作用的,它决定了处理器执行的第一条指令。

nuttx.S:
......
08000000 <_vectors>:
 8000000:    20005db4     .word    0x20005db4
 8000004:    080003d1     .word    0x080003d1       <---PC 初始值
 8000008:    08000159     .word    0x08000159
......
080003d0 <__start>:
 80003d0:    b510          push    {r4, lr}         <---处理器执行的第一条指令
 80003d2:    f000 f827     bl    8000424 <stm32_clockconfig>
 80003d6:    f000 f967     bl    80006a8 <stm32_lowsetup>
 80003de:    4b0c          ldr    r3, [pc, #48]    ; (8000410 <__start+0x40>)
......
使用《NuttX 安装脚本》一文中的方法安装 NuttX 后,反汇编文件 nuttx.S 位于 Linux 当前用户的主目录。这里的 PC 初始值是0x080003d1,指向 __start 函数的起始地址。

顺便说一下,向量表中的跳转地址都是奇数,这是因为 cortex-m3 是在Thumb状态下执行的。在向量表以外的地方,32位指令的跳转地址是奇数,16位指令的跳转地址是偶数。但指令的实际地址都是偶数,如0x080003d0。

nuttx/arch/arm/src/stm32/stm32_vectors.S:
......
_vectors:

/* Processor Exceptions */

    .word    IDLE_STACK            /* Vector  0: Reset stack pointer */
    .word    __start                /* Vector  1: Reset vector */
    .word    stm32_nmi            /* Vector  2: Non-Maskable Interrupt (NMI) */
    .word    stm32_hardfault        /* Vector  3: Hard fault */
......
这里的 .word    __start 定义了 PC 的初始值。

__start 函数的声明与定义如下:

nuttx/arch/arm/src/stm32/stm32_vectors.S:
......
    .globl        __start
......
在汇编代码中声明了全局符号 __start,相当于声明了函数。

nuttx/arch/arm/src/stm32/stm32_start.c:
......
void __start(void)
{
  const uint32_t *src;
  uint32_t *dest;

  /* Configure the uart so that we can get debug output as soon as possible */

  stm32_clockconfig();
  stm32_fpuconfig();
  stm32_lowsetup();
......
}
......
在 C 语言代码中定义了 __start 函数。

为什么 __start 是处理器执行的第一条指令?,布布扣,bubuko.com

为什么 __start 是处理器执行的第一条指令?

原文:http://blog.csdn.net/zhumaill/article/details/23426605

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!