ARM匯編編程基礎(chǔ)之四-ARM匯編偽操作
1 ;文件名:TEST.S
2 ;功能:實(shí)現(xiàn)兩個(gè)寄存器相加
3
4
5
6
7
8
9
10 ADD_SUB
11
12
13
第6、7行將傳遞給子程序的參數(shù)存放在r0和r1中,第8行調(diào)用子程序。第11、12行是子程序的代碼,完成了2個(gè)參數(shù)相加,并將結(jié)果放在r0后返回主程序。第6、8、10行的START、LOOP、ADD_SUB是標(biāo)號(hào),最經(jīng)常用于跳轉(zhuǎn)指令B和BL,由于匯編語法要求的緣故,標(biāo)號(hào)必須頂格寫(即:不能在行首有空格),否則編譯器會(huì)報(bào)錯(cuò)。與之對(duì)應(yīng)的是,匯編指令一定不能頂格寫。
很明顯分號(hào)(;)在匯編程序中是注釋符號(hào),相當(dāng)于C語言的//號(hào)。除此之外,當(dāng)然大家注意到了第3、4、5、13行是我們沒學(xué)習(xí)過的符號(hào),其實(shí)它們就是本文的重點(diǎn)——ARM匯編偽操作。首先我先來解釋這幾個(gè)偽操作,第3行定義了一個(gè)代碼段,其段名為Example,屬性為只讀,從而表示第6——12行是程序代碼(而不是程序數(shù)據(jù))。第4行表示整個(gè)程序的入口點(diǎn)(即:程序運(yùn)行的第一條指令)是第6行的MOV指令(注1)。第5行表示第6——12行的程序代碼是ARM指令,而不是thumb指令。第13行表示源代碼文件結(jié)束,其背后的含義就是:如果程序員在第13行后還寫有匯編指令,編譯器也根本不會(huì)理會(huì)這些代碼,更不會(huì)去編譯它們,當(dāng)然這些代碼也就不可能出現(xiàn)在最后的可執(zhí)行文件中。哈哈,所以請(qǐng)務(wù)必記住,在END偽操作的后面再寫代碼,那是無用功,寫了也白寫。不要不以為然喲,根據(jù)經(jīng)驗(yàn),初學(xué)者總是會(huì)犯這樣的錯(cuò)誤。
特別說明:第9行的含義是要讓程序在運(yùn)行結(jié)束后,在第9行進(jìn)行死循環(huán),從而讓整個(gè)程序定格在第9行。這一點(diǎn)也許你很困惑:在寫應(yīng)用程序時(shí),程序結(jié)束就結(jié)束了,源代碼根本不需要再去寫個(gè)死循環(huán)。但你現(xiàn)在要弄清楚:你寫應(yīng)用程序時(shí),有OS為你處理程序結(jié)束后的若干事情??墒牵悻F(xiàn)在已經(jīng)得不到OS服務(wù)。如果你不自己寫第9行的代碼,那么當(dāng)你認(rèn)為程序已經(jīng)運(yùn)行結(jié)束(第8行執(zhí)行完成)的時(shí)候,CPU不會(huì)聰明地停下來,它會(huì)繼續(xù)任勞任怨地去取指第11行,繼續(xù)運(yùn)行,這不是你所希望的。其實(shí)這還不是最糟糕的,最糟糕的是,如果你的程序沒有11-13行,那么CPU任勞任怨取出的指令其實(shí)是內(nèi)存中的隨機(jī)數(shù),但CPU卻會(huì)把它當(dāng)作指令來執(zhí)行,那么,你認(rèn)為此時(shí)會(huì)出現(xiàn)什么情況呢?哈哈,只有天知道。
當(dāng)然,偽操作遠(yuǎn)不止這幾條,下面我們?cè)賮斫榻B經(jīng)常使用的若干偽操作。
GBLA:定義全局算術(shù)變量(準(zhǔn)確說,應(yīng)該是全局符號(hào)),例如:GBLA testval
SETA:對(duì)全局算術(shù)符號(hào)進(jìn)行賦值,例如:testval
DCD:在編譯時(shí)為整數(shù)分配字存儲(chǔ)空間,例如:DCD 0x123456ab,這條偽操作將導(dǎo)致編譯器在最終的二進(jìn)制可執(zhí)行文件中分配一個(gè)字的空間,并在該空間中存放整數(shù)0x123456ab
DCB:在編譯時(shí)為整數(shù)分配字節(jié)存儲(chǔ)空間,例如:DCB ‘a’,這條偽操作將導(dǎo)致編譯器在最終的二進(jìn)制可執(zhí)行文件中分配一個(gè)字節(jié)的空間,并在該空間中存放字符a的ASCII碼
IF,ELSE及ENDIF:相當(dāng)于C語言的條件編譯,例如:
testval
編譯器編譯該段代碼的結(jié)果是:
mov r1, #9
mov r2, #9
WHILE及WEND:例如
testval SETA 1
testval SETA testval + 1
編譯器編譯該段代碼的結(jié)果是:
mov r0, #2
mov r0, #3
mov r0, #4
MACRO、MEND及MEXIT:相當(dāng)于C語言的宏替換,例如:
$label xmac $p1,$p2
; code1
$label.loop1
;code2
$label.loop2
;code3
; code4
;code5
;主程序
abc xmac subr1,de
編譯器編譯該段代碼的結(jié)果是:
;code1
abc.loop1
;code2
abc.loop2
;code3
;code4
;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)行時(shí)受到CPU的“青睞”??傊涀∫痪湓挘瑓R編偽操作是給編譯器看的,而不是給CPU看的。這是匯編偽操作與匯編指令最大的區(qū)別。
評(píng)論