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