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