arm汇编之冒泡排序
开始在ADS里面写程序后,发现自己之前对于X86汇编的学习完全归还给了我的老师门。
最直接的便是要写一个从小到大的冒泡排序。
冒泡排序的思想我想就不用赘述了。
以前c语言遍的应该很多了。
算法不成问题,可是数据结构知道是数组,可是数组在arm汇编里面该在怎么定义了?
其实,还真感觉又要从零开始了。
X86的汇编已经完全归还给了我敬爱的微机原理老师。
网上看到了一个广为流传的冒泡排序,既然写不出来,那就先学习它的精髓,说不定还能为我所用了。
代码详细的看了看。
具体翻译如下(arm汇编指令不太熟悉,就当时温习吧):
AREA Sort,CODE,READONLY :首先用AREA伪代码加上CODE,表明下面引出的将是一个代码段(于此相对的还有数据段DATA),ENTRY 和END成对出现,说明他们之间的代码是程序的主体
ENTRY:表示代码的开始
Start MOV r4,#0 :将0赋值给r4
LDR r6,=src :在使用LDR时,当格式是LDR r0,=0x022248,则第二个参数表示地址,即0x022248,同样的,当src变量代表一个数组时,需要r0寄存器指向src则需要这样赋值:LDR r0,=src 当格式是
LDR r0,[r2],则第二个参数表示寄存器,我的理解是[]符号表示取内容,r2本身表示一个寄存器地址,取内容候将其存取r0这个寄存器中跳转
到LDR R0,[R1]将存储器地址为R1的字数据读入寄存器R0 LDR
R0,[R1,#8]将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1,此句是将数据src的首地址赋值给R6
ADD r6,r6,#len:R6为数组的最后一个数组元素的地址。
数组这时是连续分配的。
Outer LDR r1,=src:将src地址即数组元素首地址赋值给R1
Inner LDR r2,[r1] :将存储器地址为r1的字数据读入r2 LDR r3,[r1,#4]:将存储器地址为R1+4的字数据读入R3
CMP r2,r3 :比较R2,R3
STRGT r3,[r1]:若(有符号数)大于,则将R3中的字数据写入以R1为地址的存储器中
STRGT r2,[r1,#4]:若大于,则将R2中的字数据写入以R1+4为地址的存储器中
ADD r1,r1,#4:R1+4赋值给R1
CMP r1,r6:R1与R6比较
BLT Inner:若是有符号数小于,即R1<R6,则跳转到Inner行执行
ADD r4,r4,#4:R4+4赋值给R4
CMP r4,#len:R4与len比较
SUBLE r6,r6,#4 :若有符号数小于或等于,则R6-4赋值给R6
BLE Outer :若有符号数小于或等于,则跳转到Outer
Stop MOV r0,#0x18 , stop一段是用来是程序退出的,第一个语句“MOV r0,#0x18”将r0赋值为0x18,这个立即数对应于宏
angel_SWIreason_ReportException。
表示r1中存放的执行状态。
语句“LDR r1,=0x20026”将r1的值设置成ADP_Stopped_ApplicationExit,该宏表示程序正常退出。
然后使用SWI,语句“SWI 0x123456”结束程序,将CPU的控制权交回调试器手中。
LDR r1,=0x20026
SWI 0x123456
AREA Array,DATA,READWRITE
src DCD 2,4,10,8,14,1,20 :数据定义伪指令DCD表示用于分配一片连续的字存储单元并用指定的数据初始化
len EQU 7*4 :这里的4是4个字节。
即是32位。
因为ARM7TDMI 是32位ARM指令集。
END:结束代码
代码很清晰。
思想很对。
执行结果貌似也很对。
可是详细看看不对。
数组的起始地址是0x00008058(此时的r6的值。
r6初值为起始地址加len,经过程序的递减后变成了起始地址),那么冒泡完后
0x00008058存储的应该是01 00 00 00(按ADS里面的内存内容显示格式),可是此时存储的是00 E8 00 E8,从0x0000805c开始才是冒泡排序后的结果。
程序肯定是有问题的。
既然要找问题,那就单步调试吧。
这里面忘了介绍怎么看内存里面存的内容了。
之前我一直找不着。
因为点击出现内存框框时,没有注意到有个start adreess。
比如这个程序里面的数组起始地址是0x0000805c,那么我们把start address通过点击递加设为
0x8000。
接着单步调试。
这是第一次排序的结果。
明显不对。
因为这个数组里面排序最大的是沉到低了,可是数0x00E800E8也参合进来,冒泡到最大的数的前面了。
这个不对。
也就是这个程序的内循环控制不对。
改正的话其实很简单。
就是程序里内循环对比较了一次。
这里我采用的方法是len定义为6*4,把len理解为偏移量应该是更合适的吧。
第一个数的地址为0x00008058,那么最后一个数的地址加上6*4 = 24的偏移量,应该是0x00008070。
这样才是正确的数组地址。
改过后再看运行结果:。