转载地址:http://blog.csdn.net/silent123go/article/details/53141316
(1)代码及注释
.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
#ifdef CONFIG_SPL_BUILD //我的uboot中没有定义这个宏,关于这个宏的介绍,请看下文
_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
#else
.globl _undefined_instruction
_undefined_instruction: .word undefined_instruction
.globl _software_interrupt
_software_interrupt: .word software_interrupt
.globl _prefetch_abort
_prefetch_abort: .word prefetch_abort
.globl _data_abort
_data_abort: .word data_abort
.globl _not_used
_not_used: .word not_used
.globl _irq
_irq: .word irq
.globl _fiq
_fiq: .word fiq
_pad: .word 0x12345678
#endif /* CONFIG_SPL_BUILD */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
#ifdef CONFIG_USE_IRQ
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
(2)反汇编代码
为了更好的理解上面用到的汇编指令,对uboot进行反汇编。使用命令:
arm-fsl-linux-gnueabi-objdump -D u-boot > u-boot.s
uboot.s就是反汇编出来的文件,以上这段代码对应的反汇编代码如下:
u-boot: file format elf32-littlearm
Disassembly of section .text:
87800000 <__image_copy_start>:
87800000: ea00000f b 87800044 <reset>
87800004: e59ff014 ldr pc, [pc, #20] ; 87800020 <_undefined_instruction>
87800008: e59ff014 ldr pc, [pc, #20] ; 87800024 <_software_interrupt>
8780000c: e59ff014 ldr pc, [pc, #20] ; 87800028 <_prefetch_abort>
87800010: e59ff014 ldr pc, [pc, #20] ; 8780002c <_data_abort>
87800014: e59ff014 ldr pc, [pc, #20] ; 87800030 <_not_used>
87800018: e59ff014 ldr pc, [pc, #20] ; 87800034 <_irq>
8780001c: e59ff014 ldr pc, [pc, #20] ; 87800038 <_fiq>
87800020 <_undefined_instruction>:
87800020: 87800120 strhi r0, [r0, r0, lsr #2]
87800024 <_software_interrupt>:
87800024: 87800180 strhi r0, [r0, r0, lsl #3]
87800028 <_prefetch_abort>:
87800028: 878001e0 strhi r0, [r0, r0, ror #3]
8780002c <_data_abort>:
8780002c: 87800240 strhi r0, [r0, r0, asr #4]
87800030 <_not_used>:
87800030: 878002a0 strhi r0, [r0, r0, lsr #5]
87800034 <_irq>:
87800034: 87800300 strhi r0, [r0, r0, lsl #6]
87800038 <_fiq>:
87800038: 87800360 strhi r0, [r0, r0, ror #6]
8780003c <_pad>:
8780003c: 12345678 eorsne r5, r4, #125829120 ; 0x7800000
87800040 <IRQ_STACK_START_IN>:
87800040: 0badc0de bleq 863703c0 <__image_copy_start-0x148fc40>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
请看语句:ldr pc, [pc, #20] ; 87800020 <_undefined_instruction>
,当要跳转到_undefined_instruction时,为什么是将当前pc的值加20后再赋给pc呢?
流水线操作:取址—>译码—>运行;
把内存中的代码取到CPU中,把e59ff014翻译成对应的命令,ldr pc,[pc,#20],然后运行。所以pc指针并不是指向当前运行的命令,而是指向当前运行的指令加8,加8超前两个指令,一个用来取址,一个用来译码,即:
pc=0x87800004+0x08=0x8780000c, pc= 0x8780000c+0x14(即20)=0x87800020
即把0x87800020地址处的数字0x87800120放到pc指针里面,即直接跳转到0x87800120地址处运行。
(3) CONFIG_SPL_BUILD介绍
这个宏定义的主要作用就是生成 BL1 文件,提到 BL1 文件肯定又会有朋友产生疑问,在这里就这个 BL1 文件给大家简单的介绍一下:
BL1 文件是一段外部代码,存放在 SD 卡或者 nandflash 上,大小为(4K\8K\16K)。除了 BL1 文件,还有 BL0 和 BL2 文件。BL0 文件是存放在 CPU 内部 IROM 中的一段固化代码,CPU 上点之后,首先去运行BL0 文件。BL2 文件是完整的 U-Boot 代码。
这三个文件之间的关系就是:BL0 运行时会将 BL1 拷贝到 CPU 的 IRAM 中,然后执行BL1,BL1 文件执行起来之后会先进行内存的初始化,之后将 BL2 文件拷贝到外部内存中运行。
(4)ARM异常向量表