匯編語言分析C語言的函數調用過程


1.要分析C語言的函數調用過程,理解匯編指令push,pop是關鍵,

在匯編中,棧的增長方式是從高地址往低地址增長,棧底在高地址,棧頂在低地址。

push eax入棧指令相當於:

ESP=ESP-4,[SS:ESP]<--eax內容;   (32 bit)

pop eax出棧指令相當於:

eax<--[SS:ESP]內容,ESP=ESP+4

                       

 2.先看下在vs2013工程下的C語言示例源碼,以__cdecl調用方式調用函數

 1 #include <stdio.h>
 2 
 3 int add(int a, int b, int c)
 4 {
 5     return (a+b+c);
 6 }
 7 
 8 int main(int argc, char *argv[])
 9 {
10     int sum = 0;
11     int a = 1;
12     int b = 2;
13     int c = 3;
14     sum = add(a,b,c);
15     return 0;
16 }

反匯編后的源碼

 1 __RTC_Initialize:
 2 01091145  jmp         _RTC_Initialize (01092D40h)  
 3 __controlfp_s:
 4 0109114A  jmp         __controlfp_s (0109376Ch)  
 5 _GetSystemTimeAsFileTime@4:
 6 0109114F  jmp         _GetSystemTimeAsFileTime@4 (01093C22h)  
 7 add:
 8 01091154h  jmp         add (010913C0h)  
 9 _DecodePointer@4:
10 01091159  jmp         _DecodePointer@4 (01093C28h)  
11 __invoke_watson:
12 0109115E  jmp         __invoke_watson (01093766h)  
13 ___report_rangecheckfailure:
14 01091163  jmp         __report_rangecheckfailure (01093940h)  
15 _RTC_GetSrcLine:
16 01091168  jmp         _RTC_GetSrcLine (010933D0h)  
17 __wmakepath_s:
18 0109116D  jmp         __wmakepath_s (0109377Eh)  
19 __CRT_RTC_INITW:
20 01091172  jmp         __CRT_RTC_INITW (0109262Ch)  
21 
22 #include <stdio.h>
23 
24 //調用函數add的地址
25 int add(int a, int b, int c)
26 {
27 010913C0  push        ebp       ;ebp=0030FB10 esp=0030FA00
28 010913C1  mov         ebp,esp      ;ebp=0030FA00
29 010913C3  sub         esp,0C0h     ;esp=0030F940
30 010913C9  push        ebx       ;保護現場,esp=0030F93C
31 010913CA  push        esi       ;esp=0030F938
32 010913CB  push        edi      ;edi=0030FB10, esp=0030F934
33 010913CC  lea         edi,[ebp-0C0h]  ;edi=0030F940
34 010913D2  mov         ecx,30h       ;初始化
35 010913D7  mov         eax,0CCCCCCCCh
36 010913DC  rep stos    dword ptr es:[edi]  
37     return (a+b+c);
38 010913DE  mov         eax,dword ptr [a]   ;取參數值,並計算
39 010913E1  add         eax,dword ptr [b]  
40 010913E4  add         eax,dword ptr [c]  
41 }
42 010913E7  pop         edi     ;恢復現場 edi=0030FB10, esp=0030F938
43 010913E8  pop         esi    ;esp=0030F93C
44 010913E9  pop         ebx     ;esp=0030F940
45 }
46 010913EA  mov         esp,ebp  ;esp=0030FA00
47 010913EC  pop         ebp    ;ebp=0030FB10, esp=0030FA04
48 010913ED  ret         ;esp=0030FA08 【__cdecl】調用方式內部沒有平衡棧,由調用者負責平棧(編譯器自動處理),【__stdcall】調用方式指令“return 0Ch”內部平棧
49 
50 //主調函數
51 int main(int argc, char *argv[])
52 {
53 01091400  push        ebp       ;將ebp內容壓棧  ebp=0030FB60  esp=0030FB14
54 01091401  mov         ebp,esp   ;esp傳給ebp  ebp=0030FB10  esp=0030FB10
55 01091403  sub         esp,0F0h  ;改變棧頂值,騰出空間,esp=esp-0F0h  esp=0030FA20
56 01091409  push        ebx       ;壓棧ebx,esi,edi,保護現場. ebp=0030FB10 esp=0030FA1C
57 0109140A  push        esi       ;esp=0030FA18
58 0109140B  push        edi     ;esp=0030FA14
59 0109140C  lea         edi,[ebp-0F0h]    ;將(ebp-0F0h)=0030FA20的值放入edi中,edi=0030FA20
60 01091412  mov         ecx,3Ch   ;ecx=3Ch,rep指令循環次數
61 01091417  mov         eax,0CCCCCCCCh  ;eax=CCCCCCCC
62 0109141C  rep stos    dword ptr es:[edi]  ;重復填充CCCCCCCC,(3Ch)次
63     int sum = 0;
64 0109141E  mov         dword ptr [sum],0   ;&sum=0030fb08, sum=0
65     int a = 1;
66 01091425  mov         dword ptr [a],1     ;&a=0030fafc, a=1
67     int b = 2;
68 0109142C  mov         dword ptr [b],2     ;&b=0030faf0, b=2
69     int c = 3;
70 01091433  mov         dword ptr [c],3     ;&c=0030fae4, c=3
71     sum = add(a,b,c);
72 0109143A  mov         eax,dword ptr [c]   ;參數按從右至左的順序壓棧, eax=3
73 0109143D  push        eax           ;esp=0030FA10
74 0109143E  mov         ecx,dword ptr [b]   ;ecx=2
75 01091441  push        ecx           ;esp=0030FA0C
76 01091442  mov         edx,dword ptr [a]   ;edx=1
77 01091445  push        edx            ;esp=0030FA08
78 01091446  call        add (01091154h)     ;調用函數add,此時會將返回函數的下一指令地址0109144B壓棧,調用前esp=0030FA04,調用后esp=0030FA08
79 0109144B  add         esp,0Ch         ;esp=0030FA14   【__cdecl】調用方式調用返回后外部平棧,【__stdcall】調用方式沒有這條指令
80 0109144E  mov         dword ptr [sum],eax  ;將值傳給變量sum
81     return 0;
82 01091451  xor         eax,eax  
83 }
84 01091453  pop         edi    ;恢復現場
85 01091454  pop         esi  
86 }
87 01091455  pop         ebx     ;esp=0030FA20
88 01091456  add         esp,0F0h  ;esp=0030FB10
89 0109145C  cmp         ebp,esp  
90 0109145E  call        __RTC_CheckEsp (01091136h)  
91 01091463  mov         esp,ebp  
92 01091465  pop         ebp     ;ebp=0030FB60 esp=0030FB14
93 01091466  ret       ;esp=0030FB18

 3.大概的過程是調用函數add前,參數先從右至左放入棧中,同時把返回地址也放入棧中。在add函數中,取出棧中的參數,執行完后返回,繼續執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM