[TOC] # 先有程序还是先有编译器 故事该从哪里开始呢?很久很久以前,是现有操作系统再有程序,还是现有程序再有操作系统?是先有程序再有编译器,还是现有编译器再有程序? 程序是啥,就是用来操作数据的机器码。 ## 黑历史 1. 最早当然是人肉打码,纸帯存储程序。 2. 接着就有了磁带,没有操作系统,loader每次也就只能boot一个程序。 3. 这下好了,as出来了,一种叫汇编的文本就能变成程序。 4. 于是操作系统就有了(Unix爷爷就是纯汇编构建出来的)。loader/kernel/装在文件系统里的program。 5. 第一个 C compiler 听说是用B语言写的。 6. 从此以后,每一个cc都是之前的cc产生的。所有的程序,产生程序的程序都有唯一一个先祖创世神。 世存最早的unix源代码: http://minnie.tuhs.org/cgi-bin/utree.pl?file=PDP7-Unix/sys 世存最早的cc: http://minnie.tuhs.org/cgi-bin/utree.pl?file=V2/c dmr解读C history https://www.bell-labs.com/usr/dmr/www/chist.html ## GCC真的都是你干的? 世人只知 gcc,不知 binutils,就如 kenerl 和 glibc。 ### 简单例子一个 1. gcc把 .c 翻译成 .s 2. as 把 .s 构造成 .o 3. ld 把 .o 和 library 一起 link 成 elf 文件 ~~~ gcc helloword.c -v -o hello /usr/lib/gcc/x86_64-linux-gnu/6/cc1 ... -march=x86-64 -auxbase helloword -version -o /tmp/ccz174Tq.s as -v --64 -o /tmp/ccxNqb6T.o /tmp/ccz174Tq.s /usr/lib/gcc/x86_64-linux-gnu/6/collect2 ... -pie -o hello /tmp/ccxNqb6T.o ... ~~~ ### 其他参数 ~~~ gcc -c helloworld.c gcc -S helloworld.c gcc -E helloworld.c ~~~ ## cross-compile linaro 4.9 比较靠谱,种类也全,完全不用自己编gcc/glibc了。`aarch64-linux-gnu-gcc`用来编linux APP,`arm-eabi-gcc`编其他所有,用的C库是newlib。 https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/aarch64-linux-gnu/gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu.tar.xz https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-eabi/gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi.tar.xz ### U-Boot build ~~~ export CROSS_COMPILE=aarch64-linux-gnu- export PATH=$PATH:/opt/gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu/bin/ make O=build_arm64 ls1088ardb_qspi_defconfig make O=build_arm64 ~~~ ### FreeRTOS build 这个target其实已经编不过了,做做例子还可以吧。改一下`makedefs` toolchain,`FLASH`加大点。 顺便聊两句,这个FreeRTOS现在完成度已经很高,可能已经一统低端的天下了。uboot的成熟度其实更高,加个线程调度,中断处理,锁就差不多可以了。不过uboot支持的芯片都是要起linux的,大才不能小用. Vxworks/nucleus 要是开源的话,可能还有条活路吧,可惜现在就烧纸吧。 ~~~ cd Demo/CORTEX_LM3S102_GCC export PATH=$PATH:/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi/bin/ make file gcc/RTOSDemo.axf gcc/RTOSDemo.axf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped ~~~ standalone.ld ~~~ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } SECTIONS { .text : { *(vectors) *(.text) *(.rodata*) *(.constdata*) _etext = .; } > FLASH .data : AT (ADDR(.text) + SIZEOF(.text)) { _data = .; *(vtable) *(.data) _edata = .; } > SRAM .bss : { _bss = .; *(.bss) _ebss = .; } > SRAM } ~~~ 1. link script 里的`AT`很重要,理解一下,运行时在`SRAM`里,存在`FLASH`里。要有代码搬这个段。 2. 自定义`section `很有用,linux的`module_init`, uboot的`command list`都靠这个实现。 3. `.data`搬或者不搬,`.bss`一定要清,`stack`要设好。 4. link的map文件非常有用:`-Map gcc/out.map`。 5. link script里的变量符号,c代码能获得其代表的地址值。 收工。