[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代码能获得其代表的地址值。
收工。