arm彙編基礎

arm彙編中的標號

標號只能由 a~z, A~Z, 0~9, “.”, _等字符組成。當標號爲 0~9 的數字時爲局部標號。
局部標號可以重複出現,使用方法如下:
標號 f: 在引用的地方向前的標號
標號 b: 在引用的地方向後的標號
局部標號代表它所在的地址,因此也可以當作變量或者函數來使用。
 


arm彙編中的分段:

(1) .section 僞操作
用戶可以通過 .section 僞操作來自定義一個段,格式如下:
.section section_name [, "flags"[, %type[,flag_specific_arguments]]]
每一個段以段名爲開始, 以下一個段名或者文件結尾爲結束。這些段都有缺省的標誌(flags) ,連接器可
以識別這些標誌。 (與 armasm 中的 AREA 相同)。
下面是 ELF 格式允許的段標誌
<標誌> 含義
a 允許段
w 可寫段
x 執行段
(2)彙編系統預定義的段名
.text @代碼段
.data @初始化數據段
.bss @未初始化數據段
.sdata @
.sbss @
需要注意的是,源程序中.bss 段應該在.text 之前。


定義入口點:

彙編程序的缺省入口是 start 標號,用戶也可以在連接腳本文件中用 ENTRY 標誌指明其它入口點。


彙編程序中的宏定義

格式如下:
.macro 宏名 參數名列表 @僞指令.macro 定義一個宏
宏體
.endm @.endm 表示宏結束
如果宏使用參數,那麼在宏體中使用該參數時添加前綴“\”。宏定義時的參數還可以使用默認值。
可以使用.exitm 僞指令來退出宏。
【例】宏定義
.macro SHIFTLEFT a, b
.if \b < 0
MOV \a, \a, ASR #-\b
.exitm
.endif
MOV \a, \a, LSL #\b
.endm


彙編程序中的常數:

(1)十進制數以非 0 數字開頭,如:123 和 9876;
(2)二進制數以 0b 開頭,其中字母也可以爲大寫;
(3)八進制數以 0 開始,如:0456,0123;
(4)十六進制數以 0x 開頭,如:0xabcd,0X123f;
(5)字符串常量需要用引號括起來,中間也可以使用轉義字符,如: “You are welcome!\n”;
(6)當前地址以“.”表示,在彙編程序中可以使用這個符號代表當前指令的地址;
(7) 表達式:在彙編程序中的表達式可以使用常數或者數值, “-”表示取負數, “~”表示取補,“<>”表示不相
等,其他的符號如:+、 -、 *、 /、 %、 <、 <<、 >、 >>、 |、 &、 ^、 !、 ==、 >=、 <=、 &&、 || 跟 C 語言中的用法相
似。


Linux 下 ARM 彙編的常用僞操作:

在前面已經提到過了一些爲操作,還有下面一些爲操作:
數據定義僞操作: .byte, .short, .long, .quad, .float, .string/.asciz/.ascii。
重複定義僞操作: .rept
賦值語句: .equ/.set 。
函數的定義:
對齊方式僞操作: .align;
源文件結束僞操作: .end;
.include 僞操作;
if 僞操作;
.global/ .globl 僞操作 ;
.type 僞操作 ;
列表控制語句;
下面是 ARM 特有的僞操 :
.reg , .unreq , .code , .thumb , .thumb_func , .thumb_set, .ltorg , .pool

數據定義僞操作:

1) .byte:單字節定義,如: .byte 1,2,0b01,0x34,072,'s' ;
2) .short:定義雙字節數據,如:.short 0x1234,60000 ;
3) .long:定義 4 字節數據,如:.long 0x12345678,23876565
4) .quad:定義 8 字節,如:.quad 0x1234567890abcd
5) .float:定義浮點數,如:.float 0f-314159265358979323846264338327\
6) .string/.asciz/.ascii:定義多個字符串,如:
.string "abcd", "efgh", "hello!"
.asciz "qwer", "sun", "world!"
.ascii "welcome\0"
需要注意的是: .ascii 僞操作定義的字符串需要自行添加結尾字符'\0'。
7) .rept:重複定義僞操作, 格式如下:
.rept 重複次數
數據定義
.endr @結束重複定義
例如:
.rept 3
.byte 0x23
.endr
8) .equ/.set: 賦值語句, 格式如下:
.equ(.set) 變量名,表達式
例如:
.equ abc 3 @讓 abc=3
 

函數的定義僞操作:

1) 函數的定義
格式如下:
函數名:
函數體
返回語句
一般的,函數如果需要在其他文件中調用, 需要用到.global 僞操作將函數聲明爲全局函數。 爲了不至於
在其他程序在調用某個 C 函數時發生混亂,對寄存器的使用我們需要遵循 APCS 準則。函數編譯器將處理爲
函數代碼爲一段.global 的彙編碼。
2) 函數的編寫應當遵循如下規則:
a1-a4 寄存器(參數、結果或暫存寄存器, r0 到 r3 的同義字)以及浮點寄存器 f0-f3(如果存在浮點協處
理器)在函數中是不必保存的;
如果函數返回一個不大於一個字大小的值,則在函數結束時應該把這個值送到 r0 中;
如果函數返回一個浮點數,則在函數結束時把它放入浮點寄存器 f0 中;
如果函數的過程改動了 sp(堆棧指針, r13)、 fp(框架指針, r11)、 sl(堆棧限制, r10)、 lr(連接寄存
器, r14)、 v1-v8(變量寄存器, r4 到 r11)和 f4-f7,那麼函數結束時這些寄存器應當被恢復爲包含在進入函
數時它所持有的值。
 

.align .end .include .incbin 僞操作
.align:用來指定數據的對齊方式,格式如下:
.align [absexpr1, absexpr2]
以某種對齊方式,在未使用的存儲區域填充值. 第一個值表示對齊方式,4, 8,16 或 32。第二個表達式值表示填充的值。
.end:表明源文件的結束。
.include:可以將指定的文件在使用.include 的地方展開,一般是頭文件。
例如:
.include “myarmasm.h”
.incbin 僞操作可以將原封不動的一個二進制文件編譯到當前文件中,使用方法如下:
.incbin "file"[,skip[,count]]
skip 表明是從文件開始跳過 skip 個字節開始讀取文件,count 是讀取的字數。
 

if 僞操作
根據一個表達式的值來決定是否要編譯下面的代碼, 用.endif 僞操作來表示條件判斷的結束, 中間可以使用.else 來決定.if 的條件不滿足的情況下應該編譯哪一部分代碼。
.if 有多個變種:
.ifdef symbol @判斷 symbol 是否定義。
.ifc string1,string2 @字符串 string1 和 string2 是否相等,字符串可以用單引號括起來。
.ifeq expression @判斷 expression 的值是否爲 0。
.ifeqs string1,string2 @判斷 string1 和 string2 是否相等,字符 串必須用雙引號括起來。
.ifge expression @判斷 expression 的值是否大於等於 0。
.ifgt absolute expression @判斷 expression 的值是否大於 0。
.ifle expression @判斷 expression 的值是否小於等於 0。
.iflt absolute expression @判斷 expression 的值是否小於 0。
.ifnc string1,string2 @判斷 string1 和 string2 是否不相等, 其用法跟.ifc 恰好相反。
.ifndef symbol, .ifnotdef symbol @判斷是否沒有定義 symbol, 跟.ifdef 恰好相反。
.ifne expression @如果 expression 的值不是 0, 那麼編譯器將編譯下面的代碼。
.ifnes string1,string2 @如果字符串 string1 和 string2 不相 等, 那麼編譯器將編譯下面的代碼。


.global .type .title .list
.global/ .globl :用來定義一個全局的符號
格式如下:
.global symbol 或者 .globl symbol
.type:用來指定一個符號的類型是函數類型或者是對象類型, 對象類型一般是數據。
格式如下:
.type 符號, 類型描述
【例】
.section .text
.type asmfunc, @function
.globl asmfunc
asmfunc:
mov pc, lr
.title:用來指定彙編列表的標題,例如:
.title “my program”
.list:用來輸出列表文件.
 


ARM 特有的僞操作:

1) .reg: 用來給寄存器賦予別名,格式如下:
別名 .req 寄存器名
2) .unreq: 用來取消一個寄存器的別名,格式如下:
.unreq 寄存器別名
注意被取消的別名必須事先定義過,否則編譯器就會報錯,這個僞操作也可以用來取消系統預製的
別名, 例如 r0, 但如果沒有必要的話不推薦那樣做。
3) .code 僞操作用來選擇 ARM 或者 Thumb 指令集,格式如下:
.code 表達式
如果表達式的值爲 16 則表明下面的指令爲 Thumb 指令,如果表達式的值爲 32 則表明下面的指令爲
ARM 指令。
4) .thumb 僞操作等同於.code 16, 表明使用 Thumb 指令, 類似的.arm 等同於.code 32。
5) .force_thumb 僞操作用來強制目標處理器選擇 thumb 的指令集而不管處理器是否支持。
6) .thumb_func 僞操作用來指明一個函數是 thumb 指令集的函數。
7) .thumb_set 僞操作的作用類似於.set, 可以用來給一個標誌起一個別名, 比.set 功能增加的。
一點是可以把一個標誌標記爲 thumb 函數的入口, 這點功能等同於 .thumb_func。
8) .ltorg 用於聲明一個數據緩衝池(literal pool)的開始,它可以分配很大的空間。
9) .pool 的作用等同 .ltorg
10) .space <number_of_bytes> {,<fill_byte>}
分配 number_of_bytes 字節的數據空間,並填充其值爲 fill_byte,若未指定該值, 缺省填充 0。(與
armasm 中的 SPACE 功能相同)
11) .word <word1> {,<word2>} …
插入一個 32-bit 的數據隊列。(與 armasm 中的 DCD 功能相同)
可以使用.word 把標識符作爲常量使用
12) .hword <short1> {,<short2>} …
插入一個 16-bit 的數據隊列。(與 armasm 中的 DCW 相同)

GNU ARM 彙編特殊字符和語法:

代碼行中的註釋符號: ‘@’
整行註釋符號: ‘#’
語句分離符號: ‘;’
直接操作數前綴: ‘#’ 或 ‘$’
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章