冒泡排序之反汇编

冒泡排序

  • 是一种简单的比较排序算法,它的特点包括以下几点:

  • 基本原理:冒泡排序基于比较和交换相邻元素的基本原理。它重复遍历整个数组,多次比较相邻的元素并根据需要交换它们的位置,以将最大(或最小)的元素逐渐冒泡到数组的右侧(或左侧)。

  • 稳定性:冒泡排序是一种稳定的排序算法,意味着相等元素的相对位置在排序后不会改变。如果两个元素的值相等,它们在排序后仍然保持相对顺序。

  • 简单易懂:冒泡排序的实现非常简单和直观,通常容易理解和实现,适用于教学和学习排序算法的初学者。

  • 效率:冒泡排序不是一个高效的排序算法,其平均和最坏情况时间复杂度都为O(n^2),其中n是数组的长度。因此,对于大型数据集,冒泡排序可能不是最佳选择。然而,在小型数据集上,它的性能可能还可以接受。

环境

vc6.0

冒泡排序实现

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
int bubbleSort(int* array,int n)
{
	int i = 0;
	int j = 0;
	int counter= 0;
	int  temp = 0;
	for ( i=0; i<n-1; i++)
	{	
		for (j=0;j<n-1-i;j++)
		{
			if (array[j]>array[j+1])
			{
				temp = array[j];
				array[j] =  array[j+1];
				array[j+1] =temp;
				counter++;
			}

		}
		if (counter = 0)
		{
			break;
		}
		printf("array[%d]=%d\n",i,array[i]);
	}
	
	return 0;
}
int main(int argc, char* argv[])
{
	int array[] ={64,55,100,150,23};
	int n = sizeof(array)/sizeof(array[0]);
	int i = 0;

	printf("sizeof(array[0]==%d\nsizeof(array)==%d\n",sizeof(array[0]),sizeof(array));
	printf("原始数组:\n");
	for ( i = 0; i<n; i++)
	{
		printf("%d\n",array[i]);
	}
	bubbleSort(&array[0],n);

	printf("\n排序后的数组:\n");
    for ( i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
	printf("Hello World!\n");
	system("pause");
	return 0;
}

main函数的汇编代码

35:   int main(int argc, char* argv[])
36:   {
0040F4A0   push        ebp   //将当前函数调用的栈底指针(ebp)的值压入栈中。这是为了保存之前调用的函数的栈帧信息,以便稍后恢复。

0040F4A1   mov         ebp,esp//将栈顶指针(esp)的值复制给基址指针(ebp),这样ebp现在指向当前函数的栈帧的基址。
0040F4A3   sub         esp,5Ch//从栈顶指针(esp)减去5Ch字节,为当前函数的局部变量和临时数据分配栈空间。
0040F4A6   push        ebx
0040F4A7   push        esi
0040F4A8   push        edi     //push ebx, push esi, push edi:将寄存器ebx、esi和edi的值压入栈中,以保存这些寄存器的值,以便在函数执行结束后能够恢复它们的原始值。这是为了保护这些寄存器的现场。
0040F4A9   lea         edi,[ebp-5Ch]//:计算相对于基址指针(ebp)的地址,将结果存储在寄存器edi中。在这种情况下,它是相对于当前函数栈帧的地址。
0040F4AC   mov         ecx,17h//将寄存器ecx设置为17h,即23的十六进制表示。这个值可能用于后续的循环或其他计算。
0040F4B1   mov         eax,0CCCCCCCCh//将寄存器eax设置为0CCCCCCCCh,这通常用于内存初始化,特别是在调试期间用于标记未初始化的内存
0040F4B6   rep stos    dword ptr [edi] //使用ecx寄存器的计数,将eax寄存器的值复制到edi指向的内存地址。这段代码可能用于初始化局部变量或清除内存区域。
37:       int array[] ={64,55,100,150,23};
0040F4B8   mov         dword ptr [ebp-14h],40h //64
0040F4BF   mov         dword ptr [ebp-10h],37h //55
0040F4C6   mov         dword ptr [ebp-0Ch],64h //100
0040F4CD   mov         dword ptr [ebp-8],96h  //150
0040F4D4   mov         dword ptr [ebp-4],17h  //23
38:       int n = sizeof(array)/sizeof(array[0]);
0040F4DB   mov         dword ptr [ebp-18h],5 //直接算出来的值给了[ebp-18]
39:       int i = 0;
0040F4E2   mov         dword ptr [ebp-1Ch],0
40:
41:       printf("sizeof(array[0]==%d\nsizeof(array)==%d\n",sizeof(array[0]),sizeof(array));
0040F4E9   push        14h //sizeof(array)的值
0040F4EB   push        4   //sizeof(sizeof(array[0]))
0040F4ED   push        offset string "sizeof(array[0]==%d\nsizeof(array"... (00423180)
0040F4F2   call        printf (004010e0)
0040F4F7   add         esp,0Ch //外平栈  压入了3值  3*4=12 所以外面平栈要12
42:       printf("原始数组:\n");
0040F4FA   push        offset string "\xd4\xad\xca\xbc\xca\xfd\xd7\xe9:\n" (00423018)
0040F4FF   call        printf (004010e0)
0040F504   add         esp,4 //外平栈
43:       for ( i = 0; i<n; i++)
0040F507   mov         dword ptr [ebp-1Ch],0
0040F50E   jmp         main+79h (0040f519)  //先跳到 0040f519地址处
0040F510   mov         eax,dword ptr [ebp-1Ch] //第二轮特征以及等等
0040F513   add         eax,1
0040F516   mov         dword ptr [ebp-1Ch],eax
0040F519   mov         ecx,dword ptr [ebp-1Ch] //ecx=0 ,第二轮eax=1
0040F51C   cmp         ecx,dword ptr [ebp-18h] //比较0和5 比较1和5
0040F51F   jge         main+98h (0040f538)  //jge 大于等于时跳到0040f538
44:       {
45:           printf("%d\n",array[i]);
0040F521   mov         edx,dword ptr [ebp-1Ch] //edx = 0
0040F524   mov         eax,dword ptr [ebp+edx*4-14h] //eax=[ebp+0*4-14h]=[ebp-14h]=64
0040F528   push        eax
0040F529   push        offset string "%d\n" (0042317c)
0040F52E   call        printf (004010e0)
0040F533   add         esp,8 //外平栈8  是printf的特征
46:       }
0040F536   jmp         main+70h (0040f510) //跳转到循环处
47:       bubbleSort(&array[0],n);
0040F538   mov         ecx,dword ptr [ebp-18h]
0040F53B   push        ecx
0040F53C   lea         edx,[ebp-14h]
0040F53F   push        edx
0040F540   call        @ILT+5(bubbleSort) (0040100a)
0040F545   add         esp,8
48:
49:       printf("\n排序后的数组:\n");
0040F548   push        offset string "%d\n\t" (00423168)
0040F54D   call        printf (004010e0)
0040F552   add         esp,4
50:       for ( i = 0; i < n; i++) {
0040F555   mov         dword ptr [ebp-1Ch],0
0040F55C   jmp         main+0C7h (0040f567)
0040F55E   mov         eax,dword ptr [ebp-1Ch]
0040F561   add         eax,1
0040F564   mov         dword ptr [ebp-1Ch],eax
0040F567   mov         ecx,dword ptr [ebp-1Ch]
0040F56A   cmp         ecx,dword ptr [ebp-18h]
0040F56D   jge         main+0E6h (0040f586)
51:           printf("%d ", array[i]);
0040F56F   mov         edx,dword ptr [ebp-1Ch]
0040F572   mov         eax,dword ptr [ebp+edx*4-14h]
0040F576   push        eax
0040F577   push        offset string "sizeof(array)==%d\n" (00422fc4)
0040F57C   call        printf (004010e0)
0040F581   add         esp,8
52:       }
0040F584   jmp         main+0BEh (0040f55e)
53:       printf("Hello World!\n");
0040F586   push        offset string "Hello World!\n" (00423008)
0040F58B   call        printf (004010e0)
0040F590   add         esp,4
54:       system("pause");
0040F593   push        offset string "pause" (00422fec)
0040F598   call        system (0040f1a0)
0040F59D   add         esp,4
55:       return 0;
0040F5A0   xor         eax,eax
56:   }
0040F5A2   pop         edi
0040F5A3   pop         esi
0040F5A4   pop         ebx
0040F5A5   add         esp,5Ch
0040F5A8   cmp         ebp,esp
0040F5AA   call        __chkesp (00401160)
0040F5AF   mov         esp,ebp
0040F5B1   pop         ebp
0040F5B2   ret

一个for循环特征

0040F555   mov         dword ptr [ebp-1Ch],0
0040F55C   jmp         main+0C7h (0040f567)
0040F55E   mov         eax,dword ptr [ebp-1Ch]
0040F561   add         eax,1
0040F564   mov         dword ptr [ebp-1Ch],eax
0040F567   mov         ecx,dword ptr [ebp-1Ch]
0040F56A   cmp         ecx,dword ptr [ebp-18h]
0040F56D   jge         main+0E6h (0040f586)
51:           printf("%d ", array[i]);
0040F56F   mov         edx,dword ptr [ebp-1Ch]
0040F572   mov         eax,dword ptr [ebp+edx*4-14h]
0040F576   push        eax
0040F577   push        offset string "sizeof(array)==%d\n" (00422fc4)
0040F57C   call        printf (004010e0)
0040F581   add         esp,8
52:       }
0040F584   jmp         main+0BEh (0040f55e)

再次精简一个for循环特征

jmp  address(高地址)
add  计数器+n
....
....
cmp  register,[ebp-x];
jxx  
....
....
jmp address(低地址)

bubbleSort

7:    int bubbleSort(int* array,int n)
8:    {
0040F390   push        ebp
0040F391   mov         ebp,esp
0040F393   sub         esp,50h
0040F396   push        ebx
0040F397   push        esi
0040F398   push        edi
0040F399   lea         edi,[ebp-50h]
0040F39C   mov         ecx,14h
0040F3A1   mov         eax,0CCCCCCCCh
0040F3A6   rep stos    dword ptr [edi]
9:        int i = 0;
0040F3A8   mov         dword ptr [ebp-4],0
10:       int j = 0;
0040F3AF   mov         dword ptr [ebp-8],0
11:       int counter= 0;
0040F3B6   mov         dword ptr [ebp-0Ch],0
12:       int  temp = 0;
0040F3BD   mov         dword ptr [ebp-10h],0
13:       for ( i=0; i<n-1; i++)
0040F3C4   mov         dword ptr [ebp-4],0
0040F3CB   jmp         bubbleSort+46h (0040f3d6)
0040F3CD   mov         eax,dword ptr [ebp-4]
0040F3D0   add         eax,1
0040F3D3   mov         dword ptr [ebp-4],eax
0040F3D6   mov         ecx,dword ptr [ebp+0Ch]//第二个参数 n
0040F3D9   sub         ecx,1
0040F3DC   cmp         dword ptr [ebp-4],ecx
0040F3DF   jge         bubbleSort+0F0h (0040f480)
14:       {
15:           for (j=0;j<n-1-i;j++)
0040F3E5   mov         dword ptr [ebp-8],0
0040F3EC   jmp         bubbleSort+67h (0040f3f7)
0040F3EE   mov         edx,dword ptr [ebp-8]
0040F3F1   add         edx,1
0040F3F4   mov         dword ptr [ebp-8],edx
0040F3F7   mov         eax,dword ptr [ebp+0Ch]
0040F3FA   sub         eax,1
0040F3FD   sub         eax,dword ptr [ebp-4]
0040F400   cmp         dword ptr [ebp-8],eax
0040F403   jge         bubbleSort+0C1h (0040f451)
16:           {
17:               if (array[j]>array[j+1])
0040F405   mov         ecx,dword ptr [ebp-8]
0040F408   mov         edx,dword ptr [ebp+8]
0040F40B   mov         eax,dword ptr [ebp-8]
0040F40E   mov         esi,dword ptr [ebp+8]
0040F411   mov         ecx,dword ptr [edx+ecx*4]
0040F414   cmp         ecx,dword ptr [esi+eax*4+4]
0040F418   jle         bubbleSort+0BFh (0040f44f)
18:               {
19:                   temp = array[j];
0040F41A   mov         edx,dword ptr [ebp-8]
0040F41D   mov         eax,dword ptr [ebp+8]
0040F420   mov         ecx,dword ptr [eax+edx*4]
0040F423   mov         dword ptr [ebp-10h],ecx
20:                   array[j] =  array[j+1];
0040F426   mov         edx,dword ptr [ebp-8]
0040F429   mov         eax,dword ptr [ebp+8]
0040F42C   mov         ecx,dword ptr [ebp-8]
0040F42F   mov         esi,dword ptr [ebp+8]
0040F432   mov         ecx,dword ptr [esi+ecx*4+4]
0040F436   mov         dword ptr [eax+edx*4],ecx
21:                   array[j+1] =temp;
0040F439   mov         edx,dword ptr [ebp-8]
0040F43C   mov         eax,dword ptr [ebp+8]
0040F43F   mov         ecx,dword ptr [ebp-10h]
0040F442   mov         dword ptr [eax+edx*4+4],ecx
22:                   counter++;
0040F446   mov         edx,dword ptr [ebp-0Ch]
0040F449   add         edx,1
0040F44C   mov         dword ptr [ebp-0Ch],edx
23:               }
24:
25:           }
0040F44F   jmp         bubbleSort+5Eh (0040f3ee)
26:           if (counter = 0)
0040F451   mov         dword ptr [ebp-0Ch],0
0040F458   cmp         dword ptr [ebp-0Ch],0
0040F45C   je          bubbleSort+0D0h (0040f460)
27:           {
28:               break;
0040F45E   jmp         bubbleSort+0F0h (0040f480)
29:           }
30:           printf("array[%d]=%d\n",i,array[i]);
0040F460   mov         eax,dword ptr [ebp-4]
0040F463   mov         ecx,dword ptr [ebp+8]
0040F466   mov         edx,dword ptr [ecx+eax*4]
0040F469   push        edx
0040F46A   mov         eax,dword ptr [ebp-4]
0040F46D   push        eax
0040F46E   push        offset string "array[i]=%d\n" (00422ff4)
0040F473   call        printf (004010e0)
0040F478   add         esp,0Ch
31:       }
0040F47B   jmp         bubbleSort+3Dh (0040f3cd)
32:
33:       return 0;
0040F480   xor         eax,eax
34:   }
0040F482   pop         edi
0040F483   pop         esi
0040F484   pop         ebx
0040F485   add         esp,50h
0040F488   cmp         ebp,esp
0040F48A   call        __chkesp (00401160)
0040F48F   mov         esp,ebp
0040F491   pop         ebp
0040F492   ret

两个for+if汇编的特征

13:       for ( i=0; i<n-1; i++)
0040F3C4   mov         dword ptr [ebp-4],0
0040F3CB   jmp         bubbleSort+46h (0040f3d6)//跳到高地址处
0040F3CD   mov         eax,dword ptr [ebp-4]//第二轮的特征以及以后的特征
0040F3D0   add         eax,1//计数器加1
0040F3D3   mov         dword ptr [ebp-4],eax
0040F3D6   mov         ecx,dword ptr [ebp+0Ch]
0040F3D9   sub         ecx,1
0040F3DC   cmp         dword ptr [ebp-4],ecx//比较
0040F3DF   jge         bubbleSort+0F0h (0040f480)//与高级运算符 相对应的指令jge
14:       {
15:           for (j=0;j<n-1-i;j++)
0040F3E5   mov         dword ptr [ebp-8],0
0040F3EC   jmp         bubbleSort+67h (0040f3f7)//跳到高地址处
0040F3EE   mov         edx,dword ptr [ebp-8]
0040F3F1   add         edx,1
0040F3F4   mov         dword ptr [ebp-8],edx
0040F3F7   mov         eax,dword ptr [ebp+0Ch]//eax = n
0040F3FA   sub         eax,1 //eax = eax -1
0040F3FD   sub         eax,dword ptr [ebp-4]//eax =eax-i
0040F400   cmp         dword ptr [ebp-8],eax//进行比较
0040F403   jge         bubbleSort+0C1h (0040f451)  //跳到高地址
16:           {
17:               if (array[j]>array[j+1])
0040F405   mov         ecx,dword ptr [ebp-8]
0040F408   mov         edx,dword ptr [ebp+8]
0040F40B   mov         eax,dword ptr [ebp-8]
0040F40E   mov         esi,dword ptr [ebp+8]
0040F411   mov         ecx,dword ptr [edx+ecx*4]
0040F414   cmp         ecx,dword ptr [esi+eax*4+4]//等
0040F418   jle         bubbleSort+0BFh (0040f44f)//
18:               {
19:                    temp = array[j];
0040F41A   mov         edx,dword ptr [ebp-8]
0040F41D   mov         eax,dword ptr [ebp+8]
0040F420   mov         ecx,dword ptr [eax+edx*4]
0040F423   mov         dword ptr [ebp-10h],ecx
20:                   array[j] =  array[j+1];
0040F426   mov         edx,dword ptr [ebp-8]
0040F429   mov         eax,dword ptr [ebp+8]
0040F42C   mov         ecx,dword ptr [ebp-8]
0040F42F   mov         esi,dword ptr [ebp+8]
0040F432   mov         ecx,dword ptr [esi+ecx*4+4]
0040F436   mov         dword ptr [eax+edx*4],ecx
21:                   array[j+1] =temp;
0040F439   mov         edx,dword ptr [ebp-8]
0040F43C   mov         eax,dword ptr [ebp+8]
0040F43F   mov         ecx,dword ptr [ebp-10h]
0040F442   mov         dword ptr [eax+edx*4+4],ecx
22:                   counter++;
0040F446   mov         edx,dword ptr [ebp-0Ch]
0040F449   add         edx,1
0040F44C   mov         dword ptr [ebp-0Ch],edx
23:               }
24:
25:           }
0040F44F   jmp         bubbleSort+5Eh (0040f3ee)
26:           if (counter = 0)
0040F451   mov         dword ptr [ebp-0Ch],0
0040F458   cmp         dword ptr [ebp-0Ch],0
0040F45C   je          bubbleSort+0D0h (0040f460)
27:           {
28:               break;
0040F45E   jmp         bubbleSort+0F0h (0040f480)
29:           }
30:           printf("array[%d]=%d\n",i,array[i]);
0040F460   mov         eax,dword ptr [ebp-4]
0040F463   mov         ecx,dword ptr [ebp+8]
0040F466   mov         edx,dword ptr [ecx+eax*4]
0040F469   push        edx
0040F46A   mov         eax,dword ptr [ebp-4]
0040F46D   push        eax
0040F46E   push        offset string "array[i]=%d\n" (00422ff4)
0040F473   call        printf (004010e0)
0040F478   add         esp,0Ch
31:       }
0040F47B   jmp         bubbleSort+3Dh (0040f3cd)
posted @ 2023-09-14 22:06  不会笑的孩子  阅读(8)  评论(0编辑  收藏  举报