CSDN话题挑战赛第1期
活动详情地址:话题PK赛
参赛话题:汇编知识分享
话题描述:我们的计算机知识就像一座金字塔,底层是数学,上面是数字电路,然后是汇编,再往上是操作系统、网络、数据库、高级编程语言、框架等等…我们不可能精通这个金子塔的每一层, 但是想走的更远就必须要了解这个金字塔的底层。因此,学习汇编并不是为了用汇编在应用层设计程序,而是为了深刻理解机器运行程序的机理。就像对于人来说不能没有常识一样,尽管常识不能直接挣钱吃饭,但它影响谈吐,影响你的判断力和决断力,决定着你接受新事物和新知识的程度。汇编就是计算机语言里面的常识和基础。
☀️作者简介:大家好我是汤姆凯特,大家可以叫我汤姆
🐋个人主页:IM汤姆凯特的CSDN博客
🎁系列专栏:【ARM嵌入式基础】
🌱每日一句:
与其他品质相比,乐观更能让你获得成功和幸福。
如何逆置数组
逆置数组这一问题比较常用的办法是数组中的首个元素和末尾元素相互交换,然后依次向数组中间遍历,直到全部交换完毕则完成逆置。 |
用下面伪代码表示,共有n个数组,i是数组首个元素,j是数组的尾元素(因为从0开始,所以n-1就是第n个元素)在while循环中用swap进行元素交换然后,改变指针的指向,最终由i>=j结束循环。
图解表示
伪代码表示
//首尾交换法逆置数组
i=0,j=n-1
while (i<j)
{
swap(a[i],a[j]);
i++;j--
}
汇编实现
要实现首尾交换必须要把数组的首地址和尾地址取到,作为数组的左右指针。然后需要定义两个存放对应地址中内容的内存变量用于内容交换。内容交换后需要分别遍历,左指针向后指向下一个元素,右指针指向前一个元素。最后以左指针的地址值大于右指针的地址值时为结束标志。
1定义左右指针
左右指针分别代表数组的首尾地址,首地址可以直接用定义数组的伪指令名称ary表示,尾地址可以用首地址加上整个数组地址的长度表示。在这里我们将首地址存到r0,尾元素的地址存到r1 。
ary:.word 0,1,2,3,4,5,6,7,8,9
.equ len,(.-ary-4)
ldr r0,=ary
add r1,r0,#len
2.采用while循环、定义内存变量暂存的寄存器
取到首尾地址之后,需要分别从首尾地址取到对应内容,然后把该内容传给没有改变的当前首尾指针。然后在对两个指针进行前后遍历(如下图),判断是否满足结束条件,如果不满足继续从改变后的地址取值,然后向改变后的地址存值,依次类推,直到满足左指针的地址大于右指针的地址结束循环。
b testfor
loop:
ldr r2,[r0]
ldr r3,[r1]
str r2,[r1],#-4
str r3,[r0],#4
testfor:cmp r0,r1
blo loop
3.遍历输出数组
1)定义一个循环变量r4
2)从内存中取数组到r5
3)在循环中依次遍历输出,直至把所有元素输出
mov r4,#1
ldr r5,=ary
b forTest
l1:
ldr r0,=fmt
ldr r1,[r5],#4
bl printf
add r4,#1
forTest:cmp r4,#n
bls l1
完整代码
ARM汇编通过首尾交换法逆置数组的完整代码如下 |
👇
.data
fmt:.asciz "%5d\n"
ary:.word 0,1,2,3,4,5,6,7,8,9
.equ n,( . - ary)/4
.equ len,(.-ary-4)
.text
.globl main
main:
stmfd sp!,{lr}
ldr r0,=ary
add r1,r0,#len
b testfor
loop:
ldr r2,[r0]
ldr r3,[r1]
str r2,[r1],#-4
str r3,[r0],#4
testfor:cmp r0,r1
blo loop
mov r4,#1
ldr r5,=ary
b forTest
l1:
ldr r0,=fmt
ldr r1,[r5],#4
bl printf
add r4,#1
forTest:cmp r4,#n
bls l1
ldmfd sp!,{lr}
mov pc, lr
.end
运行调试
总结
-
用首尾交换法逆置数组,重点是获取两个指针的初值,这里用数组前地址+数组长度获取末尾地址。
-
逆置数组中用到的所有寻址方式都是后索引寻址,即:先传值后改变。
-
取地址内容必须得在循环中取值,并且必须全部取完才能进行交换,否者会出现丢失数据的情况。
本文转载于:如何用汇编实现数组逆置
CSDN话题挑战赛第1期
活动详情地址:话题PK赛