序言:
一次有關數據結構中舞伴問題的彙編分析,由於時間問題本文僅僅是對主函數的分析。
主函數的截圖和代碼
下面是主函數的代碼:
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
出棧恢復要來的寄存器和指針的值
今天就先分析一個比較簡單,慢慢來逐漸加深難度。加油!