以前用ARM的IDE工具,使用的是ARM標准的組合語言。現在要使用GNU的工具,當然要了解一點GNU ARM彙編的不同之處。
ARM組合語言源程式敘述,一般由指令,虛擬作業,巨集指令和虛擬指令作成.ARM組合語言的設計基礎是彙編虛擬指令,彙編虛擬作業和巨集指令.
目前常用的ARM編譯環境有2種:
ARMASM: ARM公司的IDE中使用了CodeWarrior的編譯器,絕大多數windows下的開發者都在使用這一環境,完全按照ARM的規定;
GNU ARM ASM: GNU工具的ARM版本,與ARMASM略有不同;
關于CodeWarriror ARM彙編的書和文章很多,本文假定你已經完全了解ARMASM,這裡只說明GNU ARM彙編,并針對ARMASM給出說明。本文翻譯自:GNU ARM Assembler Quick Reference。
GNU ARM 彙編快速入門
任何彙編行都是如下架構:
[<label>:] [<instruction or directive>} @ comment
[<標簽>:] [<指令>} @ 註釋
GNU ARM 彙編中,任何以冒號結尾的都被認為是一個標簽,而不一定非要在一行的開始。下面是一個簡單的例子,這段組譯器定義了一個"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
GNU ARM彙編虛擬指令
下面列出了一些GNU ARM彙編虛擬指令,并給出了相應說明。
.ascii “<string>” 在彙編中定義字串并為之配置儲存空間(與armasm中的DCB功能類似)。
.asciz “<string>” 和.ascii類似, 但不配置儲存空間。
.balign <power_of_2> {,<fill_value> {,<max_padding>} }
以某種排列方式在記憶體中填補數值。(該指令與armasm中的ALIGN類似)。
power_of_2表示排列方式,其值可為4,8,16或32,單位是byte;
fill_value是要填補的值;
max_padding最大的填補界限,要求填補的bytes數超過該值,將被舍棄。
.byte <byte1> {,<byte2>} … 定義一個或多個Byte,并為之配置空間(與armasm的DCB類似)。
.code <number_of_bits> 設定指令寬度,16表示Thumb,32表示ARM assembly
(和armasm中的CODE16,CODE32相同)。
.if
.else
.endif 預編譯巨集(與armasm中的IF ELSE ENDIF相同)。
.end 彙編檔案結束旗標,常常省略不用。
.endm 巨集結束旗標。
.exitm 巨集跳出。
.macro <name> {<arg_1} {,<arg_2>} … {,<arg_N>}
定義一段名為name的巨集,arg_xxx為參數。
必須有對應的.endm結尾。
可以使用.exitm從中間跳出巨集。(與armasm中的MACRO, MEND, MEXIT相同)。
在使用巨集參數時必須這樣使用:“\<arg>”。
例如:
[CODE].macro SHIFTLEFT a, b
.if \b < 0
MOV \a, \a, ASR #-\b
.exitm
.endif
MOV \a, \a, LSL #\b
.endm
.rept <number_of_times> 迴圈執行.endr前的程式碼段number_of_times次。(與armasm中的WEN相似)
.irp <param> {,<val_1>} {,<val_2>} … 迴圈執行.endr前的程式碼段,param依次取后面給出的值。在迴圈執行的程式碼段中必須以“\<param> ”表示參數。
.endr 結束迴圈(與armasm中的WEND相似).
.equ <symbol name>, <value> 為一個標籤賦值,類似C中的#define。(與armasm中的EQU相同)
.err 編譯錯誤報告,將引起編譯的終止。
.global <symbol> 全域聲明旗標,這樣聲明的標籤將可以被外部使用。(與armasm中的EXPORT相同)。
.hword <short1> {,<short2>} …插入一個16-bit的資料佇列。(與armasm中的DCW相同)
.ifdef <symbol> 如果 <symbol>被定義,該快程式碼將被編譯。以 .endif結束。
.ifndef <symbol> 如果 <symbol>未被定義,該快程式碼將被編譯。以 .endif結束。
.include “<filename>” 包含檔案。(與armasm中的INCLUDE 或者C中的#i nclude一樣)
<register_name> .req <register_name>定義一個暫存器,.req的左邊是定義的暫存器名,右邊是使用的真正使用的暫存器。(與armasm中的RN類似)
例如:acc .req r0
[CODE].section <section_name> {,”<flags>”}開始一個新的程式碼或資料段。.text, 程式碼段;.data, 起始化資料段;.bss, 未起始化資料段。這些段都有預設的旗標(flags),聯接器可以識別這些旗標。(與armasm中的AREA相同)。
下面是ELF格式允許的段旗標
<旗標> 含義
a 允許段
w 可寫段
x 執行段
.set <variable_name>, <variable_value> 變數賦值。(與armasm中的SETA相同)
.space <number_of_bytes> {,<fill_byte>}配置number_of_bytes位元組的資料空間,并填補其值為fill_byte,若未指定該值,預設填補0。(與armasm中的SPACE功能相同)
.word <word1> {,<word2>} … 插入一個32-bit的資料佇列。(與armasm中的DCD功能相同)
GNU ARM彙編特殊字元和語法
程式碼行中的註釋象徵式: ‘@’
整行註釋象徵式: ‘#’
敘述分離象徵式: ‘;’
直接運算元前置: ‘#’ 或 ‘$’
.arm 以arm格式編譯,同code32
.thumb 以thumb格式編譯,同code16
.code16 以thumb格式編譯
.code32 以arm格式編譯
文章出處:http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135022.html
留言列表