新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM匯編編程基礎(chǔ)之四-ARM匯編偽操作

ARM匯編編程基礎(chǔ)之四-ARM匯編偽操作

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

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

本文引用地址:http://butianyuan.cn/article/201611/322181.htm

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

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

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

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

GBLA:定義全局算術(shù)變量(準(zhǔn)確說,應(yīng)該是全局符號),例如:GBLA testval

SETA:對全局算術(shù)符號進(jìn)行賦值,例如:testvalSETA9;testval SETA testval + 1

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

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

IF,ELSE及ENDIF:相當(dāng)于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

編譯器編譯該段代碼的結(jié)果是:

mov r1, #9

mov r2, #9

WHILE及WEND:例如

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

編譯器編譯該段代碼的結(jié)果是:

mov r0, #2

mov r0, #3

mov r0, #4

MACRO、MEND及MEXIT:相當(dāng)于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

編譯器編譯該段代碼的結(jié)果是:

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

EQU:相當(dāng)于C語言的宏定義,例如:testval EQU 4

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

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

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


上一頁 1 2 下一頁

關(guān)鍵詞: ARM匯編編程偽操

評論


技術(shù)專區(qū)

關(guān)閉