新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM匯編編程基礎之四-ARM匯編偽操作

ARM匯編編程基礎之四-ARM匯編偽操作

作者: 時間:2016-11-27 來源:網(wǎng)絡 收藏
掌握了基本的ARM匯編指令后,要寫出簡單的ARM匯編程序,還必須要掌握基本的ARM匯編偽操作(directive)。現(xiàn)在我們來看一個簡單的匯編程序,該程序調用子程序完成了加法操作。

1 ;文件名:TEST.S
2 ;功能:實現(xiàn)兩個寄存器相加
3AREA Example,CODE,READONLY ;聲明代碼段Example
4ENTRY ;標識程序入口
5CODE32 ;聲明32位ARM指令
6STARTMOV R0,#0 ;設置參數(shù)
7MOV R1,#10
8LOOP BL ADD_SUB ;調用子程序ADD_SUB
9B LOOP ;跳轉到LOOP
10 ADD_SUB
11ADD R0,R0,R1 ;R0 = R0 + R1
12MOV PC,LR ;子程序返回
13END ;文件結束

本文引用地址:http://2s4d.com/article/201611/322181.htm

第6、7行將傳遞給子程序的參數(shù)存放在r0和r1中,第8行調用子程序。第11、12行是子程序的代碼,完成了2個參數(shù)相加,并將結果放在r0后返回主程序。第6、8、10行的START、LOOP、ADD_SUB是標號,最經(jīng)常用于跳轉指令B和BL,由于匯編語法要求的緣故,標號必須頂格寫(即:不能在行首有空格),否則編譯器會報錯。與之對應的是,匯編指令一定不能頂格寫。

很明顯分號(;)在匯編程序中是注釋符號,相當于C語言的//號。除此之外,當然大家注意到了第3、4、5、13行是我們沒學習過的符號,其實它們就是本文的重點——ARM匯編偽操作。首先我先來解釋這幾個偽操作,第3行定義了一個代碼段,其段名為Example,屬性為只讀,從而表示第6——12行是程序代碼(而不是程序數(shù)據(jù))。第4行表示整個程序的入口點(即:程序運行的第一條指令)是第6行的MOV指令(注1)。第5行表示第6——12行的程序代碼是ARM指令,而不是thumb指令。第13行表示源代碼文件結束,其背后的含義就是:如果程序員在第13行后還寫有匯編指令,編譯器也根本不會理會這些代碼,更不會去編譯它們,當然這些代碼也就不可能出現(xiàn)在最后的可執(zhí)行文件中。哈哈,所以請務必記住,在END偽操作的后面再寫代碼,那是無用功,寫了也白寫。不要不以為然喲,根據(jù)經(jīng)驗,初學者總是會犯這樣的錯誤。

特別說明:第9行的含義是要讓程序在運行結束后,在第9行進行死循環(huán),從而讓整個程序定格在第9行。這一點也許你很困惑:在寫應用程序時,程序結束就結束了,源代碼根本不需要再去寫個死循環(huán)。但你現(xiàn)在要弄清楚:你寫應用程序時,有OS為你處理程序結束后的若干事情??墒牵悻F(xiàn)在已經(jīng)得不到OS服務。如果你不自己寫第9行的代碼,那么當你認為程序已經(jīng)運行結束(第8行執(zhí)行完成)的時候,CPU不會聰明地停下來,它會繼續(xù)任勞任怨地去取指第11行,繼續(xù)運行,這不是你所希望的。其實這還不是最糟糕的,最糟糕的是,如果你的程序沒有11-13行,那么CPU任勞任怨取出的指令其實是內(nèi)存中的隨機數(shù),但CPU卻會把它當作指令來執(zhí)行,那么,你認為此時會出現(xiàn)什么情況呢?哈哈,只有天知道。

當然,偽操作遠不止這幾條,下面我們再來介紹經(jīng)常使用的若干偽操作。

GBLA:定義全局算術變量(準確說,應該是全局符號),例如:GBLA testval

SETA:對全局算術符號進行賦值,例如:testvalSETA9;testval SETA testval + 1

DCD:在編譯時為整數(shù)分配字存儲空間,例如:DCD 0x123456ab,這條偽操作將導致編譯器在最終的二進制可執(zhí)行文件中分配一個字的空間,并在該空間中存放整數(shù)0x123456ab

DCB:在編譯時為整數(shù)分配字節(jié)存儲空間,例如:DCB ‘a’,這條偽操作將導致編譯器在最終的二進制可執(zhí)行文件中分配一個字節(jié)的空間,并在該空間中存放字符a的ASCII碼

IF,ELSE及ENDIF:相當于C語言的條件編譯,例如:

GBLA testval
testvalSETA 9
IF testval < 5
mov r0, #testval
ELSE
mov r1, #testval
ENDIF
IF :DEF:testval
mov r2, #testval
ELSE
INFO 4, "you should define testval"
ENDIF

編譯器編譯該段代碼的結果是:

mov r1, #9

mov r2, #9

WHILE及WEND:例如

GBLA testval
testval SETA 1
WHILE testval <= 3
testval SETA testval + 1
mov r0, #testval
WEND

編譯器編譯該段代碼的結果是:

mov r0, #2

mov r0, #3

mov r0, #4

MACRO、MEND及MEXIT:相當于C語言的宏替換,例如:

MACRO
$label xmac $p1,$p2
; code1
$label.loop1
;code2
BGE $label.loop1
$label.loop2
;code3
BL $p1
BGT $label.loop2
; code4
ADR r0, $p2
;code5
MEND
;主程序
abc xmac subr1,de

編譯器編譯該段代碼的結果是:

;code1
abc.loop1
;code2
BGE abc.loop1
abc.loop2
;code3
BL subr1
BGT abc.loop2
;code4
ADR r0, de
;code5

EQU:相當于C語言的宏定義,例如:testval EQU 4

EXPORT: 見“ATPCS與混合編程”一文

IMPORT:見“ATPCS與混合編程”一文

非常重要的一點是:必須深刻理解匯編偽操作是給編譯器提供某些必要的信息,以幫助編譯器正確完成程序的編譯。當編譯完成后,匯編偽操作就完成了它的歷史使命,它不可能在最終的可執(zhí)行程序的二進制代碼中留下哪怕是一點點痕跡,當然也就不可能在程序運行時受到CPU的“青睞”。總之記住一句話,匯編偽操作是給編譯器看的,而不是給CPU看的。這是匯編偽操作與匯編指令最大的區(qū)別。


上一頁 1 2 下一頁

關鍵詞: ARM匯編編程偽操

評論


技術專區(qū)

關閉