冒泡排序之反汇编
冒泡排序
-
是一种简单的比较排序算法,它的特点包括以下几点:
-
基本原理:冒泡排序基于比较和交换相邻元素的基本原理。它重复遍历整个数组,多次比较相邻的元素并根据需要交换它们的位置,以将最大(或最小)的元素逐渐冒泡到数组的右侧(或左侧)。
-
稳定性:冒泡排序是一种稳定的排序算法,意味着相等元素的相对位置在排序后不会改变。如果两个元素的值相等,它们在排序后仍然保持相对顺序。
-
简单易懂:冒泡排序的实现非常简单和直观,通常容易理解和实现,适用于教学和学习排序算法的初学者。
-
效率:冒泡排序不是一个高效的排序算法,其平均和最坏情况时间复杂度都为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)