对于操作系统来讲,从系统上电到操作系统开始运行之间,要做的事情很多。 比如,检测设备,解压内核,文件系统,设置中断,开启虚拟内存管理等等,这个是平台相关但有几乎相同的。这些看看bootloader和boot.s吧。 但对于一般的程序,运行的是链接器给的一些东西,比如crtbegin.o,其实涉及到elf里面的一些段的概念,执行main函数前,要执行一些东西比如, 1,环境变量加载, 2,c++的全局构造函数...等 说实话,现在还不很清楚arm为什么必须要有startup.s,IAR的有,realview也有,就像x86里面的BIOS一样,作为CPU引导程序。 |
ARM7 startup.s 文件解析
; A startup file for ARM by myself
; defination for mode (used for change work mode to setup stack)
MODE_USR EQU 0X10
MODE_FIQ EQU 0X11
MODE_IRQ EQU 0X12
MODE_SVC EQU 0X13
MODE_ABT EQU 0X17
MODE_UND EQU 0X1B
MODE_SYS EQU 0X1F
I_BIT EQU 0X80 ; I bit set to 1 to disable IRQ
F_BIT EQU 0X40 ; F bit set to 1 to disable FIQ
; defination of stack size
UND_StackSize EQU 0X00*4
SVC_StackSize EQU 0X02*4
ABT_StackSize EQU 0X00*4
FIQ_StackSize EQU 0X20*4
IRQ_StackSize EQU 0X20*4
USR_StackSize EQU 0X100*4
ISR_StackSize EQU (UND_StackSize + SVC_StackSize + ABT_StackSize + \
FIQ_StackSize + IRQ_StackSize)
这个ISR_StackSize就是指所有中断程序的堆栈的尺寸之和,用来在后面计算堆栈top地址用的
AREA STACK, NOINIT, READWRITE, ALIGN=4
USR_Stack space USR_StackSize 定义堆栈的空间,usr在下面,isr的在上面
USR_StackTop space ISR_StackSize
StackTop 在这里放个标号,以获得堆栈顶部的地址
Heap_Size EQU 0x100 heap好像主要是给c程序动态分配的内存使用的,如果不用 malloc, new, printf一类的,好像也可以不要(我的理解,不一定对阿)
AREA HEAP, NOINIT, READWRITE, ALIGN=4
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
AREA RESET, CODE, READONLY
ENTRY
CODE32
Vectors LDR PC, Reset_addr
LDR PC, Undef_addr
LDR PC, SWI_addr
LDR PC, PAbt_addr
LDR PC, DAbt_addr
NOP ; RESERVED VECTOR
LDR PC, [PC, #-0X0FF0] ; FOR VIC, FOR NORMAL USE LDR PC, IRQ_addr
LDR PC, FIQ_addr
Reset_addr dcd Reset_handler
Undef_addr dcd Undef_handler
SWI_addr dcd SWI_handler
PAbt_addr dcd PAbt_handler
DAbt_addr dcd DAbt_handler
FIQ_addr dcd FIQ_handler
Undef_handler b Undef_handler
SWI_handler b SWI_handler
PAbt_handler b PAbt_handler
DAbt_handler b DAbt_handler
FIQ_handler b FIQ_handler
EXPORT Reset_handler
Reset_handler LDR R0,=StackTop 先把r0设置为stack的top address
MSR CPSR_c, #MODE_UND :OR: I_BIT :OR: F_BIT ; ENTER UNDEFINED MODE
MOV SP, R0 ; SET SP TO THE TOP OF IT'S STACK
SUB R0, R0, #UND_StackSize ; CALCULATE THE NEXT STACK'S TOP
MSR CPSR_c, #MODE_SVC :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #SVC_StackSize 每设置完一种模式的堆栈,就减去,已得到下一种堆栈的top地址
MSR CPSR_c, #MODE_ABT :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #ABT_StackSize
MSR CPSR_c, #MODE_FIQ :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #FIQ_StackSize
MSR CPSR_c, #MODE_IRQ :OR: I_BIT :OR: F_BIT
MOV SP, R0
SUB R0, R0, #IRQ_StackSize
MSR CPSR_c, #MODE_USR ; NO I/F BIT SETTING
MOV SP, R0
SUB SL, R0, #USR_StackSize ; SET SL THE BOTTOM OF USER STACK, I DON'T KNOW WHAT IT MEAN 这里我有点不明白,谁能给说一下啊?
IMPORT __main __main是c环境的一个库函数,可以完成一些初始化的工作,然后跳转到用户的main()
B __main
IMPORT __use_two_region_memory 如果stack和heap在内存里分成了两段地址,就要用这个标志告诉编译器
EXPORT __user_initial_stackheap 如果使用了scatter文件来控制链接,则必须重载__user_initial_stackheap函数,否则编译器找不到heap的起始地址
__user_initial_stackheap
LDR R0, = __heap_base 为什么这么写,我也不知道,还请明白人指点一下吧。
BX LR
END