Linux下ARM彙編文法

來源:互聯網
上載者:User

第一部分 Linux下ARM彙編文法

儘管在Linux下使用C或C++編寫程式很方便,但彙編來源程式用於系統最基本的初始化,如初始化堆棧指標、設定頁表、操作 ARM的副處理器等。初始化完成後就可以跳轉到C代碼執行。需要注意的是,GNU的彙編器遵循AT&T的彙編文法,可以從GNU的網站 (www.gnu.org)上下載有關規範。

一. Linux彙編行結構

任何彙編行都是如下結構:
[:] [} @ comment
[:] [} @ 注釋
Linux ARM 彙編中,任何以冒號結尾的標識符都被認為是一個標號,而不一定非要在一行的開始。
【例1】定義一個"add"的函數,返回兩個參數的和。
.section .text, “x”
.global add @ give the symbol add external linkage
add:
ADD r0, r0, r1 @ add input arguments
MOV pc, lr @ return from subroutine
@ end of program

--------------------------------------------------------------------------------

二. Linux 組譯工具中的標號

標號只能由a~z,A~Z,0~9,“.”,_等字元組成。當標號為0~9的數字時為局部標號,局部標號可以重複出現,使用方法如下:
? 標號f: 在引用的地方向前的標號
? 標號b: 在引用的地方向後的標號

【例2】使用局部符號的例子,一段迴圈程式
1:
subs r0,r0,#1 @每次迴圈使r0=r0-1
bne 1f @跳轉到1標號去執行
局部標號代表它所在的地址,因此也可以當作變數或者函數來使用。

三. Linux組譯工具中的分段
(1).section偽操作
使用者可以通過.section偽操作來自訂一個段,格式如下:
.section section_name [, "flags"[, %type[,flag_specific_arguments]]]
每一個段以段名為開始, 以下一個段名或者檔案結尾為結束。這些段都有預設的標誌(flags),連接器可以識別這些標誌。(與armasm中的AREA相同)。
下面是ELF格式允許的段標誌
含義
a 允許段
w 可寫段
x 執行段

【例3】定義段
.section .mysection @自訂資料區段,段名為 “.mysection”
.align 2
strtemp:
.ascii "Temp string \n\0"

(2)彙編系統預定義的段名
.text @程式碼片段
.data @初始化資料區段
.bss @未初始化資料區段
.sdata @
.sbss @
需要注意的是,來源程式中.bss段應該在.text之前。

--------------------------------------------------------------------------------

四. 定義進入點
組譯工具的預設入口是 start標號,使用者也可以在串連指令檔中用ENTRY標誌指明其它進入點。
【例4】定義進入點
.section.data
.section .bss
.section .text
.globl _start
_start:

--------------------------------------------------------------------------------

五. Linux組譯工具中的宏定義
格式如下:
.macro 宏名 參數名列表 @偽指令.macro定義一個宏
宏體
.endm @.endm表示宏結束
如果宏使用參數,那麼在宏體中使用該參數時添加首碼“\”。宏定義時的參數還可以使用預設值。
可以使用.exitm偽指令來退出宏。
【例5】宏定義
.macro SHIFTLEFT a, b
.if \b ”表示不相等,其他的符號如:+、-、*、/、%、、>>、|、&、^、!、==、>=、 {,}
分配number_of_bytes位元組的資料空間,並填充其值為fill_byte,若未指定該值,預設填充0。(與armasm中的SPACE功能相同)

--------------------------------------------------------------------------------

六.word {,} …
插入一個32-bit的資料隊列。(與armasm中的DCD功能相同)
可以使用.word把標識符作為常量使用
例如:
Start:
valueOfStart:
.word Start
這樣程式的開頭Start便被存入了記憶體變數valueOfStart中。

--------------------------------------------------------------------------------

七.hword {,} …
插入一個16-bit的資料隊列。(與armasm中的DCW相同)

八. GNU ARM彙編特殊字元和文法
程式碼中的注釋符號: ‘@’
整行注釋符號: ‘#’
語句分離符號: ‘;’
直接運算元首碼: ‘#’ 或 ‘$’

第二部分 GNU的編譯器和調試工具
一. 編譯工具
1.編輯工具介紹
GNU 提供的編譯工具包括彙編器as、C編譯器gcc、C++編譯器g++、連接器ld和二進位轉換工具objcopy。基於ARM平台的工具分別為arm- linux-as、arm-linux-gcc、arm-linux-g++、arm-linux-ld和arm-linux- objcopy。GNU的編譯器功能非常強大,共有上百個操作選項,這也是這類工具讓初學者頭痛的原因。不過,實際開發中只需要用到有限的幾個,大部分可 以採用預設選項。GNU工具的開發流程如下:編寫C、C++語言或彙編來源程式,用gcc或g++產生目標檔案,編寫串連指令檔,用連接器產生最終目標檔案(elf格式),用二進位轉換工具產生可下載的二進位代碼。
(1)編寫C、C++語言或彙編來源程式
通常彙編來源程式用於系統最基本的初始化,如初始化堆棧指標、設定頁表、操作ARM的副處理器等。初始化完成後就可以跳轉到C代碼執行。需要注意的是,GNU的彙編器遵循AT&T的彙編文法,讀者可以從GNU的網站(www.gnu.org)上下載有關規範。組譯工具的預設入口是 start標號,使用者也可以在串連指令檔中用ENTRY標誌指明其它進入點(見下文關於串連指令碼的說明)。
(2)用gcc或g++產生目標檔案
如果應用程式套件組合括多個檔案,就需要進行分別編譯,最後用連接器串連起來。如筆者的引導程式包括3個檔案:init.s(彙編代碼、初始化硬體)xmrecever.c(通訊模組,採用Xmode協議)和flash.c(Flash擦寫模組)。分別用如下命令產生目標檔案: arm-linux-gcc-c-O2-oinit.oinit.s arm-linux-gcc-c-O2-oxmrecever.oxmrecever.c arm-linux-gcc-c-O2-oflash.oflash.c 其中-c命令表示只產生目標代碼,不進行串連;-o命令指明目標檔案的名稱;-O2表示採用二級最佳化,採用最佳化後可使產生的程式碼更短,運行速度更快。如果項目包含很多檔案,則需要編寫makefile檔案。關於makefile的內容,請感興趣的讀者參考相關資料。
(3)編寫串連指令檔
gcc 等編譯器內建有預設的串連指令碼。如果採用預設指令碼,則產生的目標代碼需要作業系統才能載入運行。為了能在嵌入式系統上直接運行,需要編寫自己的串連指令檔。編寫串連指令碼,首先要對目標檔案的格式有一定瞭解。GNU編譯器產生的目標檔案預設為elf格式。elf檔案由若干段(section)組成,如不特殊指明,由C來源程式產生的目標代碼中包含如下段:.text(本文段)包含程式的指令代碼;.data(資料區段)包含固定的資料,如常量、字元 串;.bss(未初始化資料區段)包含未初始化的變數、數組等。C++來源程式產生的目標代碼中還包括.fini(解構函式代碼)和. init(建構函式代碼)等。連接器的任務就是將多個目標檔案的.text、.data和.bss等段串連在一起,而串連指令檔是告訴連接器從什麼地址 開始放置這些段。例如串連檔案link.lds為:
ENTRY(begin)
SECTION
{
.=0x30000000;
.text:{*(.text)}
.data:{*(.data)}
.bss:{*(.bss)}
}
其中,ENTRY(begin)指明程式的進入點為begin標號;.=0x00300000指明目標代碼的起始地址為0x30000000,這一段地址為 MX1的片內RAM;.text:{*(.text)}表示從0x30000000開始放置所有目標檔案的程式碼片段,隨後的.data:{* (.data)}表示資料區段從程式碼片段的末尾開始,再後是.bss段。
(4)用連接器產生最終目標檔案
有了串連指令檔,如下命令可產生最終的目標檔案:arm-linux-ld –no stadlib –o bootstrap.elf -Tlink.lds init.o xmrecever.o flash.o
其中,ostadlib表示不串連系統的運行庫,而是直接從begin入口;-o指明目標檔案的名稱;-T指明採用的串連指令檔(也可以使用-Ttext address,address表示執行區地址);最後是需要串連的目標檔案列表。
(5)產生二進位代碼
串連產生的elf檔案還不能直接下載執行,通過objcopy工具可產生最終的二進位檔案:
arm-linux-objcopy –O binary bootstrap.elf bootstrap.bin
其中-O binary指定產生為二進位格式檔案。Objcopy還可以產生S格式的檔案,只需將參數換成-O srec。還可以使用-S選項,移除所有的符號資訊及重定位資訊。如果想將產生的目標代碼反組譯碼,還可以用objdump工具:
arm-linux-objdump -D bootstrap.elf
至此,所產生的目標檔案就可以直接寫入Flash中運行了。
2.Makefile執行個體
example: head.s main.c
arm-linux-gcc -c -o head.o head.s
arm-linux-gcc -c -o main.o main.c
arm-linux-ld -Tlink.lds head.o ain.o -o example.elf
arm-linux-objcopy -O binary -S example_tmp.o example
arm-linux-objdump -D -b binary -m arm example >ttt.s
二. 調試工具
Linux 下的GNU調試工具主要是gdb、gdbserver和kgdb。其中gdb和gdbserver可完成對目標板上Linux下應用程式的遠端偵錯。 gdbserver是一個很小的應用程式,運行於目標板上,可監控被調試進程的運行,並通過串口與上位機上的gdb通訊。開發人員可以通過上位機的gdb輸入命令,控制目標板上進程的運行,查看記憶體和寄存器的內容。gdb5.1.1以後的版本加入了對ARM處理器的支援,在初始化時加入- target==arm參數可直接產生基於ARM平台的gdbserver。gdb工具可以從ftp: //ftp.gnu.org/pub/gnu/gdb/上下載。
對於Linux核心的調試,可以採用kgdb工具,同樣需要通過串口與上位機上的gdb通訊,對目標板的Linux核心進行調試。可以從http://oss.sgi.com/projects/kgdb/上瞭解具體的使用方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.