ARMv7汇编代码实现冒泡排序(多重循环汇编程序)---加反汇编代码分析

本文详细展示了C语言实现冒泡排序的代码,并给出了在Ubuntu上运行的结果。随后,作者转译为汇编代码,通过反汇编分析了其工作原理,着重讨论了MVN操作在简化代码中的巧妙应用。
摘要由CSDN通过智能技术生成

首先要实现的冒泡排序C语言代码如下:

#include <cstdio>

int main()
{
    int data1[] = {1, 5, 3, 34, -2, 1, 0};
    int size = sizeof(data1) / sizeof(data1[0]);
    for(int i = 0; i < size - 1; i++)
    {
        for(int j = 0; j <size - i - 1; j++)
        {
            if(data1[j] > data1[j + 1])
            {
                int temp = data1[j];
                data1[j] = data1[j+1];
                data1[j+1] = temp;
            }
        }
    }
    for(int i = 0; i < size; i++)
        printf("%d ",data1[i]);
    printf("\r\n");
    return 0;
}

 在Ubuntu上运行结果:

汇编对应的汇编代码如下:

.equ len, 6				@数组长度减一,对应size - 1
.global _start
_start:
	ldr r0, =data1		@r0存储数组首地址
	mov r1, #0 			@r1存储外层循环的计数值 --- i
	mov r2, #0 			@r2存储内层循环的计数值 --- j
loopi:					@外层循环
	mov r3, #len
	sub r3, r3, r1 		@r3存储内层循环计数上限,对应于size - i - 1
	b loopj
next:	
	add r1, #1
	mov r2, #0
	cmp r1, #len
	bne loopi
	b finish
	
loopj: 					@内层循环
	cmp r2, r3
	beq next			@满足循环条件才执行内层循环代码,否则继续执行外层循环
	add r4, r0, r2, lsl #2 @r4用来存储内层循环数组指针[r4] == data1[r2]
	ldr r5, [r4] 		@r5存储data1[r2]
	ldr r6, [r4, #4] 	@r6存储data1[r2+1]
	add r2, #1
	cmp r5, r6			@比较R5,R6
	blt loopj			@R5 > R6则交换数组内对应位置的值,否则不交换继续运行内存循环
	
	str r5, [r4, #4]	@交换操作,直接写到存储器内
	str r6, [r4]
	b loopj
	
finish:	
	b _start


.data
data1:
	.word 1, 5, 3, 34, -2, 1, 0

汇编代码运行调试环境:CPUlator ARMv7 System Simulator

调试:

 红框内就是初始化未经过排序的数组的值,依次为:1, 5, 3, 34, -2, 1, 0

 运行完程序后该数组的值依次为:-2 0 1 1 3 5 34 ,程序运行正确

---------------------------------------------------------------------------------------------------------------------------------

反汇编分析:

在线反汇编地址:Compiler Explorer

 为了使反汇编程序尽量简单,这里将所有变量定义为全局变量并赋初值,减少出入栈操作,修改后C语言代码如下:

 反汇编代码如图:

 .LBB0_1段代表外层for循环的条件判断部分,对应:

i < size - 1

 .LBB0_3段代表内层for循环的条件判断部分,对应:

j <size - i - 1

这里面有一个MVN R2, R2的操作,就是将R2的值取反,而将一个正数n按位取反就会得到 -(n + 1)的补码,即n = 2时,~n = - 3,这一步其实相当于做了 MOV R2, -(i + 1) @仅为示意代码。我认为这一步非常巧妙,在编写汇编代码时可以好好利用该特性。

.LBB0_4段 执行的是if判断语句

.LBB0_5段执行的则是交换顺序

.LBB0_7段是内存for循环的j++操作

 .LBB0_9段是外层for循环的i++操作

剩下的就是一些变量初始化代码。

总体来看,反汇编生成的代码与我编写的汇编代码思路是一致的,并没有太大的差异,让我惊喜的是反汇编代码对于MVN的运用。

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
冒泡排序算法是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就交换位置。以下是ARMv7汇编指令实现冒泡排序的示例代码: ``` .global bubble_sort bubble_sort: push {lr} @ 保存lr寄存器 mov r3, #0 @ 初始化i=0 outer_loop: cmp r3, r1 @ 比较i和n的大小 bge end_outer_loop @ 如果i>=n,则跳转到结束 mov r4, #0 @ 初始化j=0 inner_loop: cmp r4, r1 @ 比较j和n的大小 bge end_inner_loop @ 如果j>=n,则跳转到外层循环 ldr r5, [r0, r4, lsl #2] @ 载a[j] ldr r6, [r0, r4, lsl #2] @ 载a[j+1] cmp r5, r6 @ 比较a[j]和a[j+1] ble no_swap @ 如果a[j]<=a[j+1],则跳过交换操作 str r6, [r0, r4, lsl #2] @ 存储a[j+1] str r5, [r0, r4, lsl #2] @ 存储a[j] no_swap: add r4, r4, #1 @ j=j+1 b inner_loop @ 跳转到内层循环的开头 end_inner_loop: add r3, r3, #1 @ i=i+1 b outer_loop @ 跳转到外层循环的开头 end_outer_loop: pop {pc} @ 恢复lr寄存器并返回 ``` 以上代码实现了一个全局函数`bubble_sort`,它的参数为数组地址`r0`和数组长度`r1`。该函数使用了寄存器`r3`、`r4`、`r5`和`r6`,其中`r3`和`r4`分别用于外层循环和内层循环的计数器,`r5`和`r6`分别用于存储当前比较的两个元素的值。 该函数采用了传统的双重循环实现冒泡排序,外层循环控制比较的轮数,内层循环控制每一轮比较的次数。在每次比较中,如果前一个元素大于后一个元素,则交换它们的位置。 注意,在ARMv7汇编指令中,可以通过左移操作实现乘法运算。例如,`r4, r1, lsl #2`表示将`r1`左移2位,相当于将`r1`乘以4。由于数组中每个元素都是4字节,因此可以使用左移操作来计算每个元素的偏移量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值