冒泡算法,以前学C的时候看到这名字就觉得深奥不敢看。。。。
C源代码:
main()
{
int i,j,temp;
int a[5];
for(i=0;i<5;i++)
scanf ("%d,",&a[i]); //输入5个数
for(i=0;i<=4;i++)
{
for (j=0;j<5-i;j++)
if (a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
for(i=0;i<5;i++)
printf("%5d,",a[i] );
printf("\n");
}
老做法!F8单步到跑飞CALL断下重新加载进Call分析!(好一个从句!)
00401000 83EC 14 sub esp,14 ; 14h=20,20=4*5
00401003 56 push esi
00401004 57 push edi ; 保存现场
00401005 8D7424 08 lea esi,dword ptr ss:[esp+8] ; 访问sub esp,14空出的缓冲区的首址
00401009 BF 05000000 mov edi,5 ; edi=5
0040100E 56 push esi ; 把缓冲区用来接收数字(输入循环的开始)
0040100F 68 3C804000 push asm.0040803C ; ASCII "%d,"
00401014 E8 98000000 call asm.004010B1 ; scanf
00401019 83C4 08 add esp,8 ; 恢复两个单位的堆栈(以后我们就称4个字节为一个单位吧)
0040101C 83C6 04 add esi,4 ; 指向缓冲区的指针加一个单位,即指向下一个元素
0040101F 4F dec edi ; edi--;
00401020 ^ 75 EC jnz short asm.0040100E ; edi为0就退出循环(即初始化5个元素)(输入循环的结束)
00401022 BF 05000000 mov edi,5 ; edi=5
00401027 85FF test edi,edi ; 大循环的开始(嵌套) 两个正整数相与,结果不为0所以Z为0 直到edi减小为0时或者本来就为0时这个操作才会导致Z=1 由于大循环结束处有cmp edi,1和jge跳转所以这里的jle循环算是废的了
00401029 7E 1A jle short asm.00401045 ; 把它nop掉试试 ……结果运行也没错呵呵
0040102B 8D4424 0C lea eax,dword ptr ss:[esp+C] ; 缓冲区的第二个变量放在eax,也就是冒泡中所谓的a[j+1]了
0040102F 8BF7 mov esi,edi ; 第一次循环的时候i和j相同都是5 只是在小循环里面j就是(esi)才递减了
00401031 8B48 FC mov ecx,dword ptr ds:[eax-4] ; 前一个变量(循环开始)
00401034 8B10 mov edx,dword ptr ds:[eax] ; 后一个变量
00401036 3BCA cmp ecx,edx ; 比较一下
00401038 7E 05 jle short asm.0040103F ; 如果大于则调位(小于则不调位)
0040103A 8950 FC mov dword ptr ds:[eax-4],edx
0040103D 8908 mov dword ptr ds:[eax],ecx ; 上面两句是调位代码
0040103F 83C0 04 add eax,4 ; j++;
00401042 4E dec esi ; 这里跟j++其实也差不多,只不过esi是用于计数,而没有用来寻址而已
00401043 ^ 75 EC jnz short asm.00401031 ; 循环结束
00401045 4F dec edi
00401046 83FF 01 cmp edi,1
00401049 ^ 7D DC jge short asm.00401027 ; 大循环的结束(嵌套)
0040104B 8D7424 08 lea esi,dword ptr ss:[esp+8] ; 拿第一个数组元素
0040104F BF 05000000 mov edi,5 ; 输出5次吧
00401054 8B06 mov eax,dword ptr ds:[esi] ; 输出循环的开始
00401056 50 push eax
00401057 68 34804000 push asm.00408034 ; ASCII "%5d,"
0040105C E8 1F000000 call asm.00401080
00401061 83C4 08 add esp,8
00401064 83C6 04 add esi,4
00401067 4F dec edi
00401068 ^ 75 EA jnz short asm.00401054 ; 输出循环的结束
0040106A 68 30804000 push asm.00408030
0040106F E8 0C000000 call asm.00401080 ; printf
00401074 83C4 04 add esp,4 ; 最后输出换行符
00401077 5F pop edi ; 上面这些跟开头差不多了,只不过一个输入 一个输出罢了
00401078 5E pop esi
00401079 83C4 14 add esp,14
0040107C C3 retn
00401003 56 push esi
00401004 57 push edi ; 保存现场
00401005 8D7424 08 lea esi,dword ptr ss:[esp+8] ; 访问sub esp,14空出的缓冲区的首址
00401009 BF 05000000 mov edi,5 ; edi=5
0040100E 56 push esi ; 把缓冲区用来接收数字(输入循环的开始)
0040100F 68 3C804000 push asm.0040803C ; ASCII "%d,"
00401014 E8 98000000 call asm.004010B1 ; scanf
00401019 83C4 08 add esp,8 ; 恢复两个单位的堆栈(以后我们就称4个字节为一个单位吧)
0040101C 83C6 04 add esi,4 ; 指向缓冲区的指针加一个单位,即指向下一个元素
0040101F 4F dec edi ; edi--;
00401020 ^ 75 EC jnz short asm.0040100E ; edi为0就退出循环(即初始化5个元素)(输入循环的结束)
00401022 BF 05000000 mov edi,5 ; edi=5
00401027 85FF test edi,edi ; 大循环的开始(嵌套) 两个正整数相与,结果不为0所以Z为0 直到edi减小为0时或者本来就为0时这个操作才会导致Z=1 由于大循环结束处有cmp edi,1和jge跳转所以这里的jle循环算是废的了
00401029 7E 1A jle short asm.00401045 ; 把它nop掉试试 ……结果运行也没错呵呵
0040102B 8D4424 0C lea eax,dword ptr ss:[esp+C] ; 缓冲区的第二个变量放在eax,也就是冒泡中所谓的a[j+1]了
0040102F 8BF7 mov esi,edi ; 第一次循环的时候i和j相同都是5 只是在小循环里面j就是(esi)才递减了
00401031 8B48 FC mov ecx,dword ptr ds:[eax-4] ; 前一个变量(循环开始)
00401034 8B10 mov edx,dword ptr ds:[eax] ; 后一个变量
00401036 3BCA cmp ecx,edx ; 比较一下
00401038 7E 05 jle short asm.0040103F ; 如果大于则调位(小于则不调位)
0040103A 8950 FC mov dword ptr ds:[eax-4],edx
0040103D 8908 mov dword ptr ds:[eax],ecx ; 上面两句是调位代码
0040103F 83C0 04 add eax,4 ; j++;
00401042 4E dec esi ; 这里跟j++其实也差不多,只不过esi是用于计数,而没有用来寻址而已
00401043 ^ 75 EC jnz short asm.00401031 ; 循环结束
00401045 4F dec edi
00401046 83FF 01 cmp edi,1
00401049 ^ 7D DC jge short asm.00401027 ; 大循环的结束(嵌套)
0040104B 8D7424 08 lea esi,dword ptr ss:[esp+8] ; 拿第一个数组元素
0040104F BF 05000000 mov edi,5 ; 输出5次吧
00401054 8B06 mov eax,dword ptr ds:[esi] ; 输出循环的开始
00401056 50 push eax
00401057 68 34804000 push asm.00408034 ; ASCII "%5d,"
0040105C E8 1F000000 call asm.00401080
00401061 83C4 08 add esp,8
00401064 83C6 04 add esi,4
00401067 4F dec edi
00401068 ^ 75 EA jnz short asm.00401054 ; 输出循环的结束
0040106A 68 30804000 push asm.00408030
0040106F E8 0C000000 call asm.00401080 ; printf
00401074 83C4 04 add esp,4 ; 最后输出换行符
00401077 5F pop edi ; 上面这些跟开头差不多了,只不过一个输入 一个输出罢了
00401078 5E pop esi
00401079 83C4 14 add esp,14
0040107C C3 retn