先看start.s吧
.globl _start //.global声明_start为全局符号,_start就会被连接器链接到,也就是链接脚本中的入口地址了。
_start: b reset //跳转到reset 下面的代码是设置arm的异常向量表
ldr pc, _undefined_instruction //把label后的数据或者指令内容赋值给pc
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
8种异常分别占用4个字节,因此每种异常入口处都填写一条跳转指令,直接跳转到相应的异常处理函数中,reset异常是直接跳转到reset函数,其他7种异常是用ldr将处理函数入口地址加载到pc中。
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
_pad: .word 0x12345678 /* now 16*4=64 */
__blank_zone_start:
.fill 1024*4,1,0
__blank_zone_end:
.globl _blank_zone_start
_blank_zone_start:
.word __blank_zone_start
.globl _blank_zone_end
_blank_zone_end:
.word __blank_zone_end
.balignl 16,0xdeadbeef //接下来定义的_end_vect中用.balignl来指定接下来的代码要16字节对齐,空缺的用0xdeadbeef,方便更加高效的访问内存。
接下来看第二段
mov r0, pc, lsr#28 // pc中的内容逻辑右移28位后 再传送到 R0
cmp r0, #8 // r0减去立即数8 并根据结果设置CPSR程序状态寄存器的标志位
bleq relocate
ldr r0, _blank_zone_start
ldr r1, _TEXT_BASE
sub r0, r0, r1 // r0=r0-r1
adrl r1, _start //伪指令----中等范围的地址读取
add r0, r0, r1 //r0=r0+r1
mov r1, #0 /* flags: 0->normal 1->pm */ 清零
bl init_registers //当程序无条件跳转到标号 init_registers 处执行时,同时将当前的 PC 值保存到 R14 中
ldr sp, =STACK_TRAINING //把STACK_TRAINING 的运行地址赋值为pc
#ifdef CONFIG_SVB_ENABLE
bl start_svb
#endif
#ifdef CONFIG_DDR_TRAINING_V300
ldr r0, =REG_BASE_SCTL
bl start_ddr_training /* DDR training */
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
@copy arm exception table in 0 address
adrl r0, _start
mov r1, #0
mov r2, #0x100 /* copy arm Exception table to 0 addr */
add r2, r0, r2
copy_exception_table:
ldmia r0!, {r3 - r10}
//LDMIA R0!,{R1-R4} ;R1<----[R0]
;R2<----[R0+4]
;R3<----[R0+8]
;R4<----[R0+12]
stmia r1!, {r3 - r10} 将R3-R9的数据存储到R1指向的地址上,R1值更新
cmp r0, r2
ble copy_exception_table
@ relocate U-Boot to RAM
adrl r0, _start @ r0 <- current position of code
ldr r1, _TEXT_BASE @ test if we run from flash or RAM
cmp r0, r1 @ don't reloc during debug
第三段
ldr r0, _armboot_start @ get data regions start
@ move past malloc pool
sub r0, r0, #(CONFIG_SYS_MALLOC_LEN)
@ move past gbl and a couple
sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
@ spots for abort stack
str lr, [r0] @ save caller lr in position 0将r1寄存器的值,传送到地址值为r0的(存储器)内存中
@ of saved stack
mrs r0, spsr @ get the spsr MRS指令用于将状态寄存器的内容读到通用寄存器中 程序状态保存寄存器 SPSR用于保存CPSR的状态
str lr, [r0, #4] @ save spsr in position 1 of
@ saved stack
ldr r0, [r13] @ restore r0
add r13, r13, #4 @ pop stack entry
.endm
.macro get_irq_stack @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
.macro get_fiq_stack @ setup FIQ stack
ldr sp, FIQ_STACK_START
.endm
/*
* exception handlers
*/
.align 5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
.align 5
software_interrupt:
get_bad_stack_swi
bad_save_user_regs
bl do_software_interrupt
.align 5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl do_prefetch_abort
.align 5
data_abort:
get_bad_stack
bad_save_user_regs
bl do_data_abort
.align 5
not_used:
get_bad_stack
bad_save_user_regs
bl do_not_used
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
.align 5
fiq:
get_fiq_stack
/* someone ought to write a more effective fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs
#else
.align 5
irq:
get_bad_stack
bad_save_user_regs
bl do_irq
.align 5
fiq:
get_bad_stack
bad_save_user_regs
bl do_fiq
其他部分参考链接http://blog.csdn.net/skyflying2012/article/details/25804209