FLASH存储程序的原始的二进制数据。
这里需要搞明白系统的段的的概念.
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) /cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
下面是lds链接文档
OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{ . = 0x00000000;
. = ALIGN(4); .text : { cpu/arm920t/start.o (.text) board/TQ2440/boot_init.o (.text) *(.text) }
. = ALIGN(4); .rodata : { *(.rodata) }
. = ALIGN(4); .data : { *(.data) }
. = ALIGN(4); .got : { *(.got) }
. = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .;
. = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .;}
通过上面红色部分,你可以理解系统程序是如何存放的。
我们想理解FLASH,那么我们来理解一下系统的地址空间到底是怎么回事?
系统复位,复位地址是0x0000 0000(假设系统是32位,如ARM系统被划分成 8个BANK)。
我们通常会把FLASH的放在系统复位的BANK上,那么系统复位后,便会读到第一条指令,而开始系统运作。
有一个问题,我们把u-boot.bin反汇编后,以第一条语句为例,
源:
_start: b reset
反汇编:
33f80000: ea000012 b 33f80050 <$a>
系统地址为 33f80000。这个怎么理解呢?这个是内存运行的地址,u-boot最后要把自己拷贝到内存中运行。因为他处在FLASH的引导处,系统复位运行会在ROM这边找到这句话的。CPU 在意的是 ea000012,这才是实际的指令。系统会根据这条指令来做后面的事情。
系统实际不在意地址空间的,他只会根据编译器指令做事。那么地址空间的分配便落在 系统LAYOUT者要告诉编译器,我们的系统MEMLAYOUT的方法。这个跟硬件配置有很大关系。注意nGcsXX的连接。
在编译前,程序员要显示给出TEXT_BASE的在内存中的运行起始地址。
TEXT_BASE = 0x33F80000
其实系统还需要,堆空间,异常及中断相应空间,还有栈空间。这些空间是为C运行提供环境的,只有这些环境设定好了,C语言才能够正确运行。这里暂不讨论。
只有真正理解了,地址空间,才能够对系统的运行过程有一个清晰的认识。
下面来看下源程序和汇编对照:
33f80050: e10f0000 mrs r0, CPSR33f80054: e3c0001f bic r0, r0, #31 ; 0x1f33f80058: e38000d3 orr r0, r0, #211 ; 0xd3
红色为二进制操作码,黑色加粗的语句为汇编源程序
下面看下二进制码的格式:
一条典型的ARM指令语法格式分为如下几个部分: <opcode>{<cond>}{S} <Rd>,<Rn>{,<shifter_operand>}
31-28
27-25
24-21
20
19-16
15-12
11-0 (12位)
cond
001
opcode
S
Rn
Rd
shifter_operand
shifter_operand,必须为8位的位图常熟。见整理的文档 《ARM处理器中常量的理解 》
在回过来理解下 e3c0001f bic r0, r0, #31这句话,你应该可以理解了吧!
总结:理解地址空间的原理,实际上也就理解了系统的运行过程。很重要!!!