ARM偽指令與偽操作

2022-06-28 11:09:11 字數 3838 閱讀 4829

arm偽指令有四個,分別是ldr、adr、adrl和nop,下邊對其分別介紹。

ldr 偽指令用於載入 32 位的立即數或乙個位址值到指定暫存器 。形式如  ldr register,=[expr | label_expr],與 arm 指令的 ldr 相比 , 偽指令的 ldr 的參

數有「 =」 號 。ldr有三方面的應用:

(1)用於載入常量,如 ldr r2, =0xff0 其等同於mov r2, #0xff0 但需要注意的是ldr指令載入常量可以是合法的立即數也可以不是,但是mov載入數時必須為合法的立即數。

(2)設定gpio

gpio-base equ 0xe0028000

...ldr r0, =gpio-base

ldr r1,=0x00ffff00

str r1,[r0,#0x0c]

(3)載入位址

...ldr r1,=initstack

...initstack

mov r0, lr

...兩者都是將基於 pc 相對偏移的位址值或基於暫存器相對偏移的位址值讀取到暫存器中 。形如 adr register,expr和ldr不同的是,這裡沒有等號。兩者作用類似,區別在於兩者可以載入的數的範圍不同,當位址值是位元組對齊時 , adrl取值範圍為- - 64k ~ 64k,adr為- 255 ~ 255 。

空操作指令,就是什麼也不幹,靜等時間流逝。

偽指令經過彙編編譯後就不存在了,而指令依舊存在。偽操作只是彙編過程中起作用, , 一旦彙編結束, ,偽操作也就隨之消失。另外,arm 偽指令不屬於 arm 指令集中的指令,是為了程式設計方便而定義的。

總結:其實ldr、adrl、adr的作用和用法基本類似,主要區別是載入數的範圍大小不同,ldr載入範圍最大,adrl次之,adr最小。另外,使用ldr偽指令時,運算元要帶「=」號,adrl和adr則不需要。

偽操作主要有符號定義、資料定義、指令集型別標識和其他型別四種,下邊將進行一一介紹。

符號定義偽操作用於定義 arm 匯程式設計序中的變數、對變數賦值及定義暫存器的別名等操作。常見的符號定義偽操作有如下幾種:

(1)區域性變數定義 lcla 、 lcll 及 lcls

(2)全域性變數定義 gbla 、 gbll 及 gbls

(3)變數賦值偽操作 seta 、 setl 及 sets

(4)給通用暫存器列表定義名稱rlist

a為arithmetic的首字母,意為定義乙個數字變數。l為logic的首字母,意為定義乙個邏輯變數(true或false)。s為string的首字母,意為定義乙個字串變數。舉個例子:

gbla test1             ;定義全域性數字變數test1

test1 seta 0xaa          ;test1=0xaa

gbll test2              ;定義全域性邏輯變數test2

test2 setl     ;test2=true

gbls test3             ;定義全域性字串變數test3

test3 sets 「testing」      ;test3=「testing」

rlist 形式如 name rlist ,該偽操作用於給乙個通用暫存器列表定義名稱,使用該偽操作定義的名稱可以在 ldm/stm 中使用。再舉個例子:

list rlist     ;當你定義乙個列表後,以後再用就直接寫列表名稱就好

ldmia r3!,      ;好處就是當需要多次載入同一暫存器列表時,極大地簡化了書寫

ldmia r3!,list            ;和上邊的語句效果一樣

資料定義偽操作一般用於為特定的資料分配儲存單元,同時可完成已分配儲存單元的初始化。常見的資料定義偽操作有如下幾種:

(1)dcb 用於分配一片連續的位元組儲存單元並用指定的資料初始化。

(2)dcd  用於分配一片連續的儲存單元並用指定的資料初始化。

(3)ltorg  用於宣告乙個資料緩衝池。

(4)space 用於分配一片連續的儲存區域並將其初始化為0 。

(5)map 用於定義乙個結構化的記憶體表首位址。

(6)field 用於定義乙個結構化的記憶體表的資料域。

這六個偽操作中的dcb和dcd會在文末給出乙個綜合的示例來講解其用法,這裡先從ltorg開始講。ltorg主要配合ldr偽指令一起使用,我們都知道用mov指令時,由於arm分配了12位用來儲存立即數,所以並不是所有的立即數數都能被儲存,這才有了合法與不合法的立即數之說,而ldr偽指令之所以能載入不合法的立即數的原因就是ltorg存在,使用ldr偽指令時,立即數有多大,你就可以宣告乙個相應大小的資料緩衝池來存放該立即數。當然你完全不用顯式宣告,當你不寫時,arm系統會在編譯階段自動為其補上,所以只需了解這個偽操作即可。這裡給了乙個例子,幫助你了解ltorg 的使用,看不懂可跳過,反正也不太重要。

ldr  r0,  =0xaabbccdd

eor r1 ,r1,r0

b  sub _pro

ltorg            ;宣告乙個資料緩衝池用來儲存0xaabbccdd

space的作用就如上邊所說,具體使用例子如下:

area data,data,readwrite

databuf space 1000

…map與field也是一起使用的,它倆有點像c語言中的結構體,具體例子如下,自行理解。

map 0x300         ;定義乙個結構化的記憶體表,首位址固定為0x300,包含4個域

fdata1 field 4      ;fdata1 長度為4位元組

fdata2 field 8      ;fdata2 長度為8位元組

fdata3 field 100    ;fdata3 長度為 100 位元組

fdata4 field 200    ;fdata4 長度為 200 位元組

指令集型別標識偽操作用來告訴編譯器所處理的是32 位的arm 指令還是16 位的thumb 指令,實現這一操作的操作符有arm 、code32 、thumb、code16。其中arm code32指示編譯器將要處理的是 32 位的 arm 指令,而thumb和code16指示編譯器將要處理的是 16 位的 thumb 指令。具體例子如下:

area tothumb,code,readonly

entry

arm                ;注意這裡

start

adr r0,into_thumb+1

bx r0

thumb               ;注意這裡

into_thumb

movs r0,#10

…下邊主要講四種相對常用又簡單的偽操作,由於內容相對簡單,具體示例統一在文末的綜合示例中給出。

(1)段屬性定義偽操作area

(2)源程式結尾標識end

(3)宣告程式的入口點entry

(4)定義常量或標號名稱equ

area 用於定義乙個**段或資料段, area  偽操作指示彙編器彙編新的**段或資料段。

end 偽操作用於通知編譯器已經到了源程式的結尾。相當於漢語中的句號吧。

entry

偽操作用於指定匯程式設計序的入口點。在乙個完整的匯程式設計序中(乙個程式可以包含多個原始檔)至少要有乙個entry, 但在乙個原始檔裡不能使用多個entry。

equ

偽操作用於為程式中的常量、標號等定義乙個等效的字元名稱。

該例子綜了以上學習的偽指令和偽操作,主要作用是將src中內容複製到dst中。

ARM彙編偽指令

global,local,set,equ global 使得符號對聯結器可見,變為對整個工程可用的全域性變數,通俗講就是定義全域性變數 eg global symbol local set 給乙個全域性變數或區域性變數賦值,和.equ的功能一樣 eg set symbol expr set star...

ARM彙編偽指令

資料定義偽指令 彙編控制偽操作 雜項.global,local,set,equ 使得符號對聯結器可見,變為對整個工程可用的全域性變數,通俗講就是定義全域性變數 eg global symbol 給乙個全域性變數或區域性變數賦值,和.equ的功能一樣 eg set symbol expr set st...

ARM彙編偽指令

用來做注釋。可以在行首也可以在 後面同一行直接跟,和c語言中 類似 做注釋,一般放在行首,表示這一行都是注釋而不是 以冒號結尾的是標號 點號在gnu彙編中表示當前指令的位址 立即數前面要加 或 表示這是個立即數 global start 給 start外部鏈結屬性 section text 指定當前...