1. 獲取 GNU 工具鏈
因爲是用 GNU 工具鏈編譯能在 Cortex-m3 上跑的程序,因此在 ARM 官網上找到 GNU 的工具鏈,GNU 工具鏈下載 。
注:EABI 是嵌入式應用程序二進制接口的簡稱。可執行目標文件必須符合該規則,從而可以跨開發工具鏈使用。
2. 開發流程
GNU 工具鏈也包含了編譯器、彙編器和鏈接器等等工具,所以我們的代碼可以使用 C/C++ 語言,也可以使用彙編語言,流程如下所示:
3. 示例程序
接下來我們使用 GNU 工具鏈編譯可以在 Cortex-m3 內核上跑的代碼。
3.1 第一個程序
3.1.1 計算 10+9+8…+1 的值,彙編程序如下:
//example1.s
/* 定義常數 */
.equ STACK_TOP, 0x20000800
.text //預定義的關鍵字,表示後面內容是代碼
.global _start // 聲明標號 _start 爲全局標號, 可以被其它目標文件使用
.code 16 //指示程序代碼使用 thumb 編寫
.syntax unified //指示使用統一彙編語言語法
_start:
.word STACK_TOP, start // 定義 MSP 的初始值爲 0x2000_0800
.type start, function //start 爲復位向量,聲明爲function 是爲了不讓彙編器清除 LSB,因爲 LSB 如果爲 0, 則表示要進入 ARM 狀態, 這是不允許的
start:
movs r0, #10
movs r1, #0
loop:
adds r1, r0
subs r0, #1
bne loop
deadloop:
b deadloop
.end //指示程序文件的結束
3.1.2 GNU 工具鏈編譯
//1. 使用 GNU 的彙編器編譯 .s 文件, -mcpu 和 -mthumb 決定使用的指令集
$ arm-none-eabi-as -mcpu=cortex-m3 -mthumb example1.s -o example1.o
//2. 使用 GNU 的鏈接器進行鏈接 -Ttext 0x0 表示將鏈接到 0 地址
$ arm-none-eabi-ld -Ttext 0x0 -o example1.out example1.o
//3. 使用 GNU 的二進制產生器 產生二進制文件
$ arm-none-eabi-objcopy -Obinary example1.out example1.bin
//4. 使用 GNU 的反彙編器 反彙編代碼,結果如下圖所示
$ arm-none-eabi-objdump -S example1.out > example1.list
反彙編後的 example1.list 文件內容:
3.2 鏈接多個文件
通常工程包含多個目標文件,需要鏈接在一起,生成最終的可執行文件。這裏,我們新建 2 個彙編文件,分別爲 example2a.s 和 example2b.s 。前者只包含向量表,後者包含正常的代碼。這裏,**.global 關鍵字就有用了—在文件中傳遞全局符號。
3.2.1 example2a.s 和 example2b.s ,彙編程序如下:
//example2a.s
.equ STACK_TOP, 0x20000800
.global vectors_table
.global start
.global nmi_handler
.code 16
.syntax unified
vectors_table:
.word STACK_TOP, start, nmi_handler, 0x00000000
.end
//example2b.s
.text
.global _start
.global start
.global nmi_handler
.code 16
.syntax unified
.type start, function
.type nmi_handler, function
start:
_start:
movs r0, #10
movs r1, #0
loop:
adds r1, r0
subs r0, #1
bne loop
deadloop:
b deadloop
nmi_handler:
bx lr
.end
3.2.2 GNU 工具鏈編譯鏈接
//1. 使用 GNU 的彙編器編譯分別編譯 .s 文件, -mcpu 和 -mthumb 決定使用的指令集
$ arm-none-eabi-as -mcpu=cortex-m3 -mthumb example2a.s -o example2a.o
$ arm-none-eabi-as -mcpu=cortex-m3 -mthumb example2b.s -o example2b.o
//2. 使用 GNU 的鏈接器將 2 個目標文件進行鏈接 -Ttext 0x0 表示將鏈接到 0 地址
$ arm-none-eabi-ld -Ttext 0x0 -o example2.out example2a.o example2b.o
//3. 使用 GNU 的二進制產生器 產生二進制文件
$ arm-none-eabi-objcopy -Obinary example2.out example2.bin
//4. 使用 GNU 的反彙編器 反彙編代碼,結果如下圖所示
$ arm-none-eabi-objdump -S example2.out > example2.list
反彙編後的 example2.list 文件內容: