序言:
一次有关数据结构中舞伴问题的汇编分析,由于时间问题本文仅仅是对主函数的分析。
主函数的截图和代码
下面是主函数的代码:
int main()
{
int m,n,k;
system("color f0");//控制台颜色
printf("请输入三个数字(以空格隔开)第一个代表男生人数,第二个代表女生人数,第三个代表共需要几对舞伴,请输入:\n");
scanf("%d%d%d",&m,&n,&k);
//建立两个队列 存放男女编号
LinkQueue Q1;
InitQueue(&Q1);
for(int i=1;i<=m;i++)
{
EnQueue(&Q1,i);
}
LinkQueue Q2;
InitQueue(&Q2);
for(int p=1;p<=n;p++)
{
EnQueue(&Q2,i);
}
//用两个指针 遍历两个队列 打印编号
QDataNode *p1,*p2;
p1=Q1->front->next;
p2=Q2->front->next;
for(int o=0;o<k;o++)//循环遍历k次
{
printf("%d %d\n",p1->x,p2->x);
p1=p1->next;
p2=p2->next;
}system("pause");
return 0;
下面是汇编代码的分析
汇编的截图:
下面是汇编的代码:
38: int main()
39: {
00401170 push ebp
00401171 mov ebp,esp
00401173 sub esp,68h
00401176 push ebx
00401177 push esi
00401178 push edi
00401179 lea edi,[ebp-68h]
0040117C mov ecx,1Ah
00401181 mov eax,0CCCCCCCCh
00401186 rep stos dword ptr [edi]
40: int m,n,k;
41: system("color f0");
00401188 push offset string "color f0" (004350b0)
0040118D call system (0040a470)
00401192 add esp,4
42: printf("请输入三个数字(以空格隔开)第一个代表男生人数,第二个代表女生人数,第三个代表共需要几对舞伴,请输入:\n");
00401195 push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xc8\xfd\xb8\xf6\xca\xfd\xd7\xd6\xa3\xa8\xd2\xd4\
0040119A call printf (0040a3f0)
0040119F add esp,4
43: scanf("%d%d%d",&m,&n,&k);
004011A2 lea eax,[ebp-0Ch]
004011A5 push eax
004011A6 lea ecx,[ebp-8]
004011A9 push ecx
004011AA lea edx,[ebp-4]
004011AD push edx
004011AE push offset string "%d%d%d" (0043502c)
004011B3 call scanf (0040a390)
004011B8 add esp,10h
44: //建立两个队列 存放男女编号
45: LinkQueue Q1;
46: InitQueue(&Q1);
004011BB lea eax,[ebp-10h]
004011BE push eax
004011BF call @ILT+0(InitQueue) (00401005)
004011C4 add esp,4
47: for(int i=1;i<=m;i++)
004011C7 mov dword ptr [ebp-14h],1
004011CE jmp main+69h (004011d9)
004011D0 mov ecx,dword ptr [ebp-14h]
004011D3 add ecx,1
004011D6 mov dword ptr [ebp-14h],ecx
004011D9 mov edx,dword ptr [ebp-14h]
004011DC cmp edx,dword ptr [ebp-4]
004011DF jg main+83h (004011f3)
48: {
49: EnQueue(&Q1,i);
004011E1 mov eax,dword ptr [ebp-14h]
004011E4 push eax
004011E5 lea ecx,[ebp-10h]
004011E8 push ecx
004011E9 call @ILT+15(EnQueue) (00401014)
004011EE add esp,8
50: }
004011F1 jmp main+60h (004011d0)
51: LinkQueue Q2;
52: InitQueue(&Q2);
004011F3 lea edx,[ebp-18h]
004011F6 push edx
004011F7 call @ILT+0(InitQueue) (00401005)
004011FC add esp,4
53: for(int p=1;p<=n;p++)
004011FF mov dword ptr [ebp-1Ch],1
00401206 jmp main+0A1h (00401211)
00401208 mov eax,dword ptr [ebp-1Ch]
0040120B add eax,1
0040120E mov dword ptr [ebp-1Ch],eax
00401211 mov ecx,dword ptr [ebp-1Ch]
00401214 cmp ecx,dword ptr [ebp-8]
00401217 jg main+0BBh (0040122b)
54: {
55: EnQueue(&Q2,i);
00401219 mov edx,dword ptr [ebp-14h]
0040121C push edx
0040121D lea eax,[ebp-18h]
00401220 push eax
00401221 call @ILT+15(EnQueue) (00401014)
00401226 add esp,8
56: }
00401229 jmp main+98h (00401208)
57: //用两个指针 遍历两个队列 打印编号
58: QDataNode *p1,*p2;
59: p1=Q1->front->next;
0040122B mov ecx,dword ptr [ebp-10h]
0040122E mov edx,dword ptr [ecx]
00401230 mov eax,dword ptr [edx+4]
00401233 mov dword ptr [ebp-20h],eax
60: p2=Q2->front->next;
00401236 mov ecx,dword ptr [ebp-18h]
00401239 mov edx,dword ptr [ecx]
0040123B mov eax,dword ptr [edx+4]
0040123E mov dword ptr [ebp-24h],eax
61: for(int o=0;o<k;o++)//循环遍历k次
00401241 mov dword ptr [ebp-28h],0
00401248 jmp main+0E3h (00401253)
0040124A mov ecx,dword ptr [ebp-28h]
0040124D add ecx,1
00401250 mov dword ptr [ebp-28h],ecx
00401253 mov edx,dword ptr [ebp-28h]
00401256 cmp edx,dword ptr [ebp-0Ch]
00401259 jge main+118h (00401288)
62: {
63: printf("%d %d\n",p1->x,p2->x);
0040125B mov eax,dword ptr [ebp-24h]
0040125E mov ecx,dword ptr [eax]
00401260 push ecx
00401261 mov edx,dword ptr [ebp-20h]
00401264 mov eax,dword ptr [edx]
00401266 push eax
00401267 push offset string "%d %d\n" (00435024)
0040126C call printf (0040a3f0)
00401271 add esp,0Ch
64: p1=p1->next;
00401274 mov ecx,dword ptr [ebp-20h]
00401277 mov edx,dword ptr [ecx+4]
0040127A mov dword ptr [ebp-20h],edx
65: p2=p2->next;
0040127D mov eax,dword ptr [ebp-24h]
00401280 mov ecx,dword ptr [eax+4]
00401283 mov dword ptr [ebp-24h],ecx
66: }system("pause");
00401286 jmp main+0DAh (0040124a)
00401288 push offset string "pause" (0043501c)
0040128D call system (0040a470)
00401292 add esp,4
67: return 0;
00401295 xor eax,eax
68: }
00401297 pop edi
00401298 pop esi
00401299 pop ebx
0040129A add esp,68h
0040129D cmp ebp,esp
0040129F call __chkesp (0040a350)
004012A4 mov esp,ebp
004012A6 pop ebp
004012A7 ret
00401170 push ebp
00401171 mov ebp,esp
00401173 sub esp,68h
00401176 push ebx
00401177 push esi
00401178 push edi
00401179 lea edi,[ebp-68h]
0040117C mov ecx,1Ah
00401181 mov eax,0CCCCCCCCh
00401186 rep stos dword ptr [edi]
这些代码实在进行一些函数初始化的工作,进行寄存器的压入和保存的,为接下来要进行的工作做准备。
00401188 push offset string “color f0” (004350b0)
0040118D call system (0040a470)
00401192 add esp,4
这里是调用了系统中的一些指令使得控制台变为白色的
004011A2 lea eax,[ebp-0Ch]
004011A5 push eax
004011A6 lea ecx,[ebp-8]
004011A9 push ecx
004011AA lea edx,[ebp-4]
004011AD push edx
004011AE push offset string “%d%d%d” (0043502c)
004011B3 call scanf (0040a390)
004011B8 add esp,10h
读取用户输入的三个数值,并且这三个数值的地址是连在一起,并且这里还要注意,栈的是按照“先进后出”的原则的,所以最下面的[ebp-4]的地址中存放的是m
004011BB lea eax,[ebp-10h]
004011BE push eax
004011BF call @ILT+0(InitQueue) (00401005)
004011C4 add esp,4
再度提升栈的空间,然后把Q1放入,再调用初始化函数
004011FF mov dword ptr [ebp-1Ch],1
00401206 jmp main+0A1h (00401211)
00401208 mov eax,dword ptr [ebp-1Ch]
0040120B add eax,1
0040120E mov dword ptr [ebp-1Ch],eax
00401211 mov ecx,dword ptr [ebp-1Ch]
00401214 cmp ecx,dword ptr [ebp-8]
00401217 jg main+0BBh (0040122b)
这里是for循环,把1放入[ebp-1Ch]即
然后强制跳转到00401211这个地址
然后产生比较也就是判断
然后决定向那个地方跳转
下面是for循环中语句
00401219 mov edx,dword ptr [ebp-14h]
0040121C push edx
0040121D lea eax,[ebp-18h]
00401220 push eax
00401221 call @ILT+15(EnQueue) (00401014)
00401226 add esp,8
调用了一个函数EnQueue()上面的代码也是和函数的初始化以及一些寄存器的压栈
00401229 jmp main+98h (00401208)
强制跳转到00401208
00401208 mov eax,dword ptr [ebp-1Ch]
0040120B add eax,1
0040120E mov dword ptr [ebp-1Ch],eax
到这里for循环就算分析的差不多了
不过还有就是最为重要的跳出去的代码
00401217 jg main+0BBh (0040122b)
0040122B mov ecx,dword ptr [ebp-10h]
0040122E mov edx,dword ptr [ecx]
00401230 mov eax,dword ptr [edx+4]
00401233 mov dword ptr [ebp-20h],eax
00401236 mov ecx,dword ptr [ebp-18h]
00401239 mov edx,dword ptr [ecx]
0040123B mov eax,dword ptr [edx+4]
0040123E mov dword ptr [ebp-24h],eax
这里是进行了p1和p2的初始化
00401241 mov dword ptr [ebp-28h],0
00401248 jmp main+0E3h (00401253)
0040124A mov ecx,dword ptr [ebp-28h]
0040124D add ecx,1
00401250 mov dword ptr [ebp-28h],ecx
00401253 mov edx,dword ptr [ebp-28h]
00401256 cmp edx,dword ptr [ebp-0Ch]
00401259 jge main+118h (00401288)
接着再进行一个循环
进行的是for(int o=0;o<k;o++)
0040125B mov eax,dword ptr [ebp-24h]
0040125E mov ecx,dword ptr [eax]
00401260 push ecx
00401261 mov edx,dword ptr [ebp-20h]
00401264 mov eax,dword ptr [edx]
00401266 push eax
00401267 push offset string “%d %d\n” (00435024)
0040126C call printf (0040a3f0)
00401271 add esp,0Ch
对printf()函数的调用
00401274 mov ecx,dword ptr [ebp-20h]
00401277 mov edx,dword ptr [ecx+4]
0040127A mov dword ptr [ebp-20h],edx
0040127D mov eax,dword ptr [ebp-24h]
00401280 mov ecx,dword ptr [eax+4]
00401283 mov dword ptr [ebp-24h],ecx
p1=p1->next;p2=p2->next;
00401286 jmp main+0DAh (0040124a)
00401288 push offset string “pause” (0043501c)
0040128D call system (0040a470)
00401292 add esp,4
这里执行的是让程序停止下来的
system(“pause”);(我为了方便调试写的…)
00401295 xor eax,eax
return 0;
00401297 pop edi
00401298 pop esi
00401299 pop ebx
0040129A add esp,68h
0040129D cmp ebp,esp
0040129F call __chkesp (0040a350)
004012A4 mov esp,ebp
004012A6 pop ebp
004012A7 ret
出栈恢复要来的寄存器和指针的值
今天就先分析一个比较简单,慢慢来逐渐加深难度。加油!