stm32 開發中startup.s文件中常見的命令功能
由於C的普及以及編譯器的發展,越來越多的軟件工程師在編程時很少有機會接觸到匯編語言。在ARM的開發中,我們不可避免的會遇到啟動文件的編寫,在KEIL環境中一般采用了startup.s的文件作為啟動代碼,很多工程師一見到這個文件就很頭痛,這裏我簡單地介紹一些常見的匯編指令、偽指令,希望對大家有所幫助,下次見到.s文件時也不會覺得那麽難以接受。
提醒下大家,在匯編代碼中是不區分大小寫的,這點和C語言不太一樣,所以一下的指令在很多時候是用小寫的。不過我個人意見是匯編最好全部用大寫字母,這樣方便閱讀。
本筆記有很多是基礎的知識,適合一些初級的工程師學習。很多指令和語法是匯編通用的,如果你耐心的全部看完,相信一定對你的開發工作有幫助。
1. REQUIRE8和PRESERVE8
在定義堆棧的時候,我們經常會看到REQUIRE8和PRESERVE8偽指令,這兩個指令是告訴編譯器保證8字節對齊。因為ARM的編譯器默認是4字節對齊的,而在堆棧的操作中很多時候我們會用到LDRD和STRD這樣的雙字傳送指令,所以這裏的存儲器就要求要8字節對齊。
實際操作中,REQUIRE8和PRESERVE8並不會直接完成對齊的操作,而只是更改編譯器中的編譯屬性,真正的對齊操作是由ALIGN來完成的。
2. AREA
AREA 偽指令用來定義一個存儲器的區域,一般我們把它叫做段(sector).其語法格式如下:
AREA 段名稱 屬性1,屬性2, ……
需要註意的是如果段名稱是由數字或者特殊字符開頭,則需要用||把段名稱括起來。例如 |3_Code| 或者|.code|
屬性部分用來表示該存儲器段的相關屬性,多個屬性之間用逗號隔開,常用的屬性如下:
- NOINIT : 非初始化
- CODE :用於定義代碼段,定義了該屬性則默認READONLY屬性
- DATA : 用於定義數據段,定義了該屬性則默認READWRITE屬性
- READWRITE/READONLY : 用來標示本段是只讀還是可讀可寫
- ALIGN : 存儲器的訪問的對齊, 一般定義為ALIGN = N,其中N表示對齊的字數,例如:
ALIGN = 2表示對齊方式是2的2次方,即4字節對齊
ALIGN = 3 標示對齊方式是2的3次方, 即8字節對齊
- COMMON : 該屬性用來定義一個通用的存儲區,不包含任何代碼和數據。在不同源文件中定義的COMMON區域共享一個存儲區域。
3. THUMB(CODE16)、ARM(CODE32)
這兩個偽指令通知編譯器,其後的指令為16位的Thumb指令還是32位的ARM指令。由於ARM7的內核支持這兩種指令模式,而且允許在同一個代碼中,對這兩個模式進行切換,所以在使用ARM和Thumb指令混合編程的代碼中,用這兩條偽指令來切換。
在Cortex-M系列內核中,由於采用了Thumb2的指令集,所以不存在切換ARM的指令模式。
4. EXPORT,IMPORT,EXTERN
這兩個偽指令用來聲明或引用一個全局的變量(函數)標號。在匯編和C的混合編程代碼中,可以通過這兩個偽指令來傳遞變量(函數)標號。其中EXPORT也可以用GLOBAL代替。
需要註意的是雖然匯編語言不區分大小寫,但變量(函數)的標號是區分大小寫的。
IMPORT的用法和EXTERN類似。它們主要的區別在於如果外部文件未定義本標號,是否添加到本源文件的符號表中,對一般的程序員來講不用關心這個差別。
如果在EXPORT和IMPORT 後面有[WEAK]的參數,表明本指令聲明的標號如果在其他地方遇到同名的標號,本標號的優先級最低。
5. SPACE
SPACE用來保留一個指定大小的存儲空間。該語句比較簡單,例如:
SPACE 100
表示在本指令開始的地址劃分出一個100字節大小的空間。
6. SPACE
SPACE用來保留一個指定大小的存儲空間。該語句比較簡單,例如:
SPACE 100
表示在本指令開始的地址劃分出一個100字節大小的空間
7. ENTRY
ENTRY用於指定匯編程序的入口點,有點像C語言中的main函數。一個完整的匯編應用程序至少需要一個ENTRY。
8. INCBIN
有時候我們會遇到這樣的問題,我有一個圖片或數據編譯成了BIN文件,這樣我如何把它嵌入到我的程序中來呢? INCBIN這個偽指令就給我們帶來這樣的用處,它可以把一段已經編譯好的BIN文件包含到當前的源文件中,被包含的文件不做任何改動。
例如:
我們要把一個編譯好的字符串加入源文件來,我們可以這樣寫:
EXPORT string_1 ; 聲明這個字符串的標號,方便其他程序調用
String_1
INCBIN string_1.bin ; 載入該字符的bin文件
在*.c的文件中,我們可以直接調用String_1[]這個數組。
9. GET, INCLUDE
GET和INCLUDE類似,它們用於將一個源文件包含到當前的源文件中,並將被包含的源文件在當前位置進行匯編處理。這個和C語言中的”#include”類似
10. END
END偽指令用來通知編譯器到了源程序的結尾。他和ENTRY相對應,一個應用程序只應該有一個END。
以上內容摘自Triton.Zhang。
stm32 開發中startup.s文件中常見的命令功能