编译器是如何将芯片执行的第一个指令放到芯片起始地址的？
前言 本人8年嵌入式Linux BSP开发经验，关于U-Boot的开发经验如下： 所以，相信有资格回答这个问题。 本文8000多字，掏心带你深入理解背后的原理，需要你耐心往下看。除了问题本身，你还将收获： 这个问题往深了说就涉及到了编译原理。 在计算机世界中，其实每一次链接过程都是由链接脚本控制的。那么什么是链接脚本呢？简单说就是由链接器命令语言书写的，给链接器看的，主要的目的是描述输入文件中的段（如text段、data段、bss段等）如何在输出文件中组装，并控制输出文件的存储布局。 那么上面提到的链接器、链接脚本、输入文件、输出文件分别是指什么呢？ 读万卷书，不如走一步路。动动手指，编译一下U-Boot就知道了，如果你还不清楚怎么编译或者没有环境的话，建议你参考我的文章搭建一个： 下面是编译结果，截取重点如下： 这里的链接器就是 aarch64-linux-gnu-ld.bfd。链接脚本就是u-boot.lds，用“-T”命令行选项来指定。输入文件就是各个目录下编译好的build-in.o以及lib库。输出文件就是u-boot，通过“-o”命令行选项来指定。 千呼万唤始出来，我们来看看u-boot.lds这个链接脚本长的帅不帅： 咋一看是不是挺帅的，好，那我们来认识一下这位大帅哥。 他首先是一个文本文件，里面有一系列命令。其中SECTIONS该命令用于描述输出文件的内存布局，它后面跟着花括号中的一些列符号分配和输出段的描述。该命令的第一行设定了特殊符号“.”的值，“.”值是位置计数器。如果不用其他方式指定输出段的地址，地址从位置计数器的当前值开始计算。在SECTIONS命令的最开始，位置计数器的值是0。 接下来定义输出段“.text”。冒号是必需的格式。在输出段的名称后有一个花括号，里面可以列举放入该输出段的输入段。“*”是匹配任何文件名的通配符。表达式“*(.__image_copy_start)”表示所有输入文件中的所有“.__image_copy_start”输入段。接下来是表达式“arch/arm/cpu/armv8/start.o （.text*）”表示所有输入文件中的“.text”段的arch/arm/cpu/armv8/start.o。 题主的关切点来了： U-Boot执行的第一条指令用链接脚本中的术语叫做“入口点”。链接脚本中使用ENTRY命令来设置。参数是一个符号名称：ENTRY(symol)，这里的符号就是"_start"。这里的“_start”是什么呢？就是0x0，查看方式如下： 那么0x0后面放什么呢？摘取关键部分如下： 0x0后面放text段，text段里面先放什么呢？就是“*(.__image_copy_start)”，是什么呢，还是0x0： 下面就是主角的真面目了，就是arch/arm/cpu/armv8/start.o (.text*)，再揭开面纱一睹真容： 懂了吧，现在知道为啥“b reset”就会放在存储介质的0地址了吧，圆满解答题主的问题。 2022/04/03更新（没想到阅读量已快1千，感谢知友的赞同和追更）： 关于链接脚本的入口点的补充： 前面提到，可以使用ENTRY链接脚本命令设置入口点。其实链接器支持多种方式设置入口点，会按照如下优先顺序尝试设定入口点： 光说不练假把式，实验来检验。 实验一：屏蔽链接脚本中的“ENTRY(_start)"和"arch/arm/cpu/armv8/start.o" 重新编译后，查看映射表不再是从“b reset”开始了，直接是“__arm_smccc_smc”函数： 这种情况直接走顺序4，而.text段描述并没有指定具体内容，顺着肯定就是.efi_runtime段的第一个字节了。 实验二：保留ENTRY(_start)，并将“arch/arm/cpu/armv8/start.o”替换为“*(.text)*”： 这种情况扔能通过"ENTRY(_start)"找到对应入口： 但无法直接看出是哪个.o，实际确实是“arch/arm/cpu/armv8/start.o”，因为只有"arch/arm/cpu/armv8/start.S"定义了".globl  _start"。 这种情况直接走顺序3。 实验三：删除“ENTRY(_start)"，并将“arch/arm/cpu/armv8/start.o”替换为“*(.text)*”： 扔能找到arch/arm/cpu/armv8/start.S作为入口： 这种情况直接走顺序4。 剩下的实验就交给你啦。 关注 @闪光吧Linux，围观更多U-Boot、Linux内核、嵌入式Linux学习等方面的干货。 如果你有技术问题、学习路线、简历修改、技术面试等方面的个性化需求，可以戳下方的卡片向我发起咨询： 对啦，近期在知乎分享开了3个专栏，分别是： 可以帮助你进阶嵌入式Linux，让你按图索骥，有需要可以点开。 感谢支持呀~