Oct 16, 2015 課程紀錄

[2015q3 Week #5] [編輯共筆內容]

本週課程重點

公告

影片觀賞

GNU Toolchain

介紹完編譯工具後,來講點大概編譯的流程還有格式

Compile flow 

先來看這張圖:

 

.c 和 .s 我想大家比較常見,所以就解釋一下 .coff 和 .elf 是什麼:

GAS program format (AT&T)

由一個簡短的 code 來介紹,在程式的section 會看到 `.` ,是定義一些 control information,如 .file , .global

注意,在後來的 ARM 中,一律以 "SVC" (Supervisor Call) 取代 "SWI",但指令編碼完全一致

==> ARM Instruction Set Quick Reference Card

以下簡介 ELF 中個別 section 的意義: (注意: ELF section 的命名都由 `.` 開頭) 

寫程式的要點

Procedures

來複習一下名詞

==> "argument" 和 "parameter" 在中文翻譯一般寫「參數」或「引數」,常常混淆

==> "argument" 的重點是「傳遞給函式的形式」,所以在 C 語言程式寫 `int main(int argc, char *argv[])` 時,我們稱 argc 是 argument count,而 argv 是 argument vector

==> "parameter" 的重點是「接受到的數值」,比方說 C++ 有 parameterized type,就是說某個型態可以當作另外一個型態的「參數」,換個角度說,「型態」變成像是數值一樣的參數了。

==> https://en.wikipedia.org/wiki/Parameter_(computer_programming)

在撰寫程式常常會使用呼叫( call ),在上圖中高階語言直接將參數傳入即可,那麼在組語的時候是如何實作的呢?是透過暫存器? Stack ?  memory ? In what order ?我們必須要有個 protocol 來規範

ARM Procedure Call Standard (AAPCS)

以下測試一個參數數量為 4 和 5的程式:

程式編譯後,用 objdump 組譯會得到類似以下:

紅框標注的是比左邊多出的程式碼,從這裡可以看到參數 1-4 是存在 R0-R3,而第 5個參數存在原本 sp + 4  的位置,隨著程式碼進行 R0-R3 存在 stack 中,圖下為 stack 恢復前的樣子:

因此若寫到需要輸入5個或以上的參數時,就必須存取外部記憶體,這也導致效能的損失。

==> xorg xserver 的最佳化案例

Standard ARM C program address space

下圖為 ARM C program 標準配置記憶體空間的概念圖:

Accessing operands

通常 procedure 存取 operands 透過以下幾種方式:

用幾張圖來表現出存取 operands 時,stack 的變化:

圖下為 passed on a register:

 

圖下為存取 local variables:

Target Triple

在使用 Cross Compiler 時,gcc 前面總有一串術語,例如:

這樣 `arm-none-linux-gnueabi-`稱為 target tripe,通常規則如下:

<target>[<endian>][-<vender>]-<os>[-<extra-info>]

先以常見 x86 的平台為例子:

gcc  下 -v 可以看到以下:

<target>-<vendor>-<os> 的形式

Android Toolchain:

<target>-<os>-<extra-info>

androideabi : 雖然 Android 本身是 Linux 但其 ABI 細節跟一般 linux 不太一樣

Linaro ELF toolchain:

<target>-<vender>-<extra-info>

vender = none

extra-info = eabi

Linaro Linux toolchain:

<target><endian>-<os>-<extra-info>

extra-info:

eabi: EABI

hf : Hard float, 預設有 FPU

Linaro big-endian Linux toolchain:

<target><endian>-<vender>-<extra-info>

endian = be = big-endian

Buildroot 2015-02

<target>-<vender>-<os>-<extra-info>

extra-info:

uclibc 用 uclibc (通常預設是 glibc, uclibc 有些細節與 glibc 不同)

gnu : 無意義

eabi : 採用 EABI

NDS32 Toolchain:

<target><endian>-<os>

Andes 家的,應該淺顯易懂不用解釋

由以上眾多 pattern 大概可以歸納出一些事情:

vender 欄位變化很大,os 欄位可不填。若不填的話,通常代表 Non-OS (Bare-metal)

source: http://kitoslab.blogspot.tw/2015/08/target-triple.html

編譯器原理

為何我們要理解編譯器?這是電腦科學最早的思想體系

[ Interpreter, Compiler, JIT from scratch ]

[ Virtual Machine Constructions for Dummies ]

[ How A Compiler Works ]

實做案例:

jit-construct : Brainf*ck

rubi : Ruby-like JIT compiler