arm匯編之冒泡排序
其實(shí),還真感覺(jué)又要從零開(kāi)始了。X86的匯編已經(jīng)完全歸還給了我敬愛(ài)的微機(jī)原理老師。
網(wǎng)上看到了一個(gè)廣為流傳的冒泡排序,既然寫(xiě)不出來(lái),那就先學(xué)習(xí)它的精髓,說(shuō)不定還能為我所用了。
代碼詳細(xì)的看了看。具體翻譯如下(arm匯編指令不太熟悉,就當(dāng)時(shí)溫習(xí)吧):
AREA Sort,CODE,READONLY :首先用AREA偽代碼加上CODE,表明下面引出的將是一個(gè)代碼段(于此相對(duì)的還有數(shù)據(jù)段DATA),ENTRY 和END成對(duì)出現(xiàn),說(shuō)明他們之間的代碼是程序的主體
ENTRY:表示代碼的開(kāi)始
Start MOV r4,#0 :將0賦值給r4
LDR r6,=src :在使用LDR時(shí),當(dāng)格式是LDR r0,=0x022248,則第二個(gè)參數(shù)表示地址,即0x022248,同樣的,當(dāng)src變量代表一個(gè) 數(shù)組時(shí),需要r0寄存器指向src則需要這樣賦值:LDR r0,=src 當(dāng)格式是LDR r0,[r2],則第二個(gè)參數(shù)表示寄存器,我的理解是[]符號(hào)表示取內(nèi)容,r2本身表示一個(gè)寄存器地址,取內(nèi)容候?qū)⑵浯嫒0這個(gè)寄存器中跳轉(zhuǎn)到 LDR R0,[R1]將存儲(chǔ)器地址為R1的字?jǐn)?shù)據(jù)讀入寄存器R0 LDR R0,[R1,#8]將存儲(chǔ)器地址為R1+8的字?jǐn)?shù)據(jù)讀入寄存器R0,并將新地址R1+8寫(xiě)入R1,此句是將數(shù)據(jù)src的首地址賦值給R6
ADD r6,r6,#len:R6為數(shù)組的最后一個(gè)數(shù)組元素的地址。數(shù)組這時(shí)是連續(xù)分配的。
Outer LDR r1,=src:將src地址即數(shù)組元素首地址賦值給R1
Inner LDR r2,[r1] :將存儲(chǔ)器地址為r1的字?jǐn)?shù)據(jù)讀入r2
LDR r3,[r1,#4]:將存儲(chǔ)器地址為R1+4的字?jǐn)?shù)據(jù)讀入R3
CMP r2,r3 :比較R2,R3
STRGT r3,[r1]:若(有符號(hào)數(shù))大于,則將R3中的字?jǐn)?shù)據(jù)寫(xiě)入以R1為地址的存儲(chǔ)器中
STRGT r2,[r1,#4]:若大于,則將R2中的字?jǐn)?shù)據(jù)寫(xiě)入以R1+4為地址的存儲(chǔ)器中
ADD r1,r1,#4:R1+4賦值給R1
CMP r1,r6:R1與R6比較
BLT Inner:若是有符號(hào)數(shù)小于,即R1
ADD r4,r4,#4:R4+4賦值給R4
CMP r4,#len:R4與len比較
SUBLE r6,r6,#4 :若有符號(hào)數(shù)小于或等于,則R6-4賦值給R6
BLE Outer :若有符號(hào)數(shù)小于或等于,則跳轉(zhuǎn)到Outer
Stop MOV r0,#0x18 , stop一段是用來(lái)是程序退出的,第一個(gè)語(yǔ)句“MOV r0,#0x18”將r0賦值為0x18,這個(gè)立即數(shù)對(duì)應(yīng)于宏angel_SWIreason_ReportException。表示r1中存放的執(zhí)行狀態(tài)。語(yǔ)句“LDR r1,=0x20026”將r1的值設(shè)置成ADP_Stopped_ApplicationExit,該宏表示程序正常退出。然后使用SWI,語(yǔ)句“SWI 0x123456”結(jié)束程序,將CPU的控制權(quán)交回調(diào)試器手中。
LDR r1,=0x20026
SWI 0x123456
AREA Array,DATA,READWRITE
src DCD 2,4,10,8,14,1,20 :數(shù)據(jù)定義偽指令DCD表示用于分配一片連續(xù)的字存儲(chǔ)單元并用指定的數(shù)據(jù)初始化
len EQU 7*4 :這里的4是4個(gè)字節(jié)。即是32位。因?yàn)锳RM7TDMI是32位ARM指令集。
END:結(jié)束代碼
代碼很清晰。思想很對(duì)。執(zhí)行結(jié)果貌似也很對(duì)。
可是詳細(xì)看看不對(duì)。數(shù)組的起始地址是0x00008058(此時(shí)的r6的值。r6初值為起始地址加len,經(jīng)過(guò)程序的遞減后變成了起始地址),那么冒泡完后0x00008058存儲(chǔ)的應(yīng)該是01 00 00 00(按ADS里面的內(nèi)存內(nèi)容顯示格式),可是此時(shí)存儲(chǔ)的是00 E8 00 E8,從0x0000805c開(kāi)始才是冒泡排序后的結(jié)果。程序肯定是有問(wèn)題的。既然要找問(wèn)題,那就單步調(diào)試吧。
這里面忘了介紹怎么看內(nèi)存里面存的內(nèi)容了。之前我一直找不著。因?yàn)辄c(diǎn)擊出現(xiàn)內(nèi)存框框時(shí),沒(méi)有注意到有個(gè)start adreess。比如這個(gè)程序里面的數(shù)組起始地址是0x0000805c,那么我們把start address通過(guò)點(diǎn)擊遞加設(shè)為0x8000。
接著單步調(diào)試。
這是第一次排序的結(jié)果。明顯不對(duì)。因?yàn)檫@個(gè)數(shù)組里面排序最大的是沉到低了,可是數(shù)0x00E800E8也參合進(jìn)來(lái),冒泡到最大的數(shù)的前面了。這個(gè)不對(duì)。也就是這個(gè)程序的內(nèi)循環(huán)控制不對(duì)。
改正的話其實(shí)很簡(jiǎn)單。就是程序里內(nèi)循環(huán)對(duì)比較了一次。這里我采用的方法是len定義為6*4,把len理解為偏移量應(yīng)該是更合適的吧。第一個(gè)數(shù)的地址為0x00008058,那么最后一個(gè)數(shù)的地址加上6*4 = 24的偏移量,應(yīng)該是0x00008070。這樣才是正確的數(shù)組地址。
評(píng)論