1. 程式人生 > >分析簡單的c語言函式編譯得到的X86彙編程式碼(VS2013)

分析簡單的c語言函式編譯得到的X86彙編程式碼(VS2013)

檢視原始碼生成的彙編程式碼:單步除錯->除錯->視窗->反彙編

 

總結:

①、函式被呼叫時,實參值賦值給函式棧中的形參,使用以下步驟:

       I、call函式前實參值壓棧   

       II、函式中分配區域性變數的程式碼執行完   

       III、使用原始棧頂值 ebp 的正偏移量(實參),和負偏移量(形參),配合mov指令來實現值傳遞,如:

                mov [ebp,ebp-3] [ebp+16,ebp+13]         //計算時不可遺漏了棧中 push pc 和 push ebp帶來的esp變化

 

②、vc編譯c原始碼時,給函式中的臨時變數在棧中分配的儲存區域,不是根據臨時變數的多少制定的,而是一個固定值 204B

 

③、vc在棧中給函式中臨時變數分配儲存單元后,會執行一系列彙編程式碼,給這些儲存單元賦上初始值,本例中每個位元組都是十六進位制 0xcc ;   執行完賦初始值操作後,才開始進行實參形參值傳遞

 

④、vc函式中的臨時變數包括以下種類: ①、函式形參  ②、函式體內定義的臨時變數   ③、函式返回值

 

⑤、本例子中 sum 函式的返回值使用 暫存器eax來傳遞;  一般化的適用於所有情況的函式返回值要使用棧來傳遞給呼叫本函式的程式碼吧。

 

 

c原始碼:

int sum(int a, int b)
{
    int c = a + b;
    return c;
}

int main()
{
    int a = 2, b = 3;
    int c = 0;
    c=sum(a, b);
    return 1;
}

 

彙編程式碼:

int sum(int a, int b)
{
00E813C0  push        ebp

                 ;ebp值入棧儲存
00E813C1  mov         ebp,esp          ;將當前棧頂值esp賦值給ebp
00E813C3  sub         esp,0CCh        ;esp=esp-204,空出204B的棧空間用於本函式的臨時變數(這裡為何是204B不理解,本函式不優化的情況下臨時變數只需要4*4=16B)

                                                          ;繼續解釋上行程式碼,本組合語言採用遞減棧,即push dword值語句等價於下面①②

                                                           ①、mov dword ptr [esp],dword值   ②、mov esp esp-4  
00E813C9  push        ebx                  ;ebx值入棧儲存
00E813CA  push        esi                   ;esi值入棧儲存  
00E813CB  push        edi                   ;edi值入棧儲存 
00E813CC  lea         edi,[ebp-0CCh]  ;給edi=當前段中ebp的地址-204(即00E813C3行執行完後的esp值)
00E813D2  mov         ecx,33h            ;給ecx賦值33h (十進位制數51,由204/4計算得出,204是棧中儲存臨時變數的位元組數)
00E813D7  mov         eax,0CCCCCCCCh   ;給eax賦值 0CCCCCCCCh ,本值作為棧中臨時變數區每個dword元素的初始值
00E813DC  rep stos    dword ptr es:[edi]  ;給棧中204B的臨時變數區位元組賦初始值。本語句由以下①②指令複合而來

                                                            ①、rep 指令 :重複執行指令ecx次(每執行完一次ecx=ecx-1,然後判斷是否繼續執行)

                                                            ②、stos  dword ptr es:[edi] : I、move dword ptr es:[edi] eax  II、mov edi edi+4
    int c = 0;
00E813DE  mov         dword ptr [c],0  ; 這裡應該是 mov dword ptr [ebp-8,ebp-11],0 

                                                   插入以下本編譯器UI中未生成的但實際執行了的語句(此時記憶體中資料排布見下面分析):

                                                                 mov [ebp,ebp-3] [ebp+16,ebp+13]          ; sum函式形參b=sum函式實參b

                                                                 mov [ebp-4,ebp-7] [ebp+12,ebp+9]         ; sum函式形參a=sum函式實參a

                                                                 
    c = a + b;
00E813E5  mov         eax,dword ptr [a]  
00E813E8  add         eax,dword ptr [b]  
00E813EB  mov         dword ptr [c],eax  
    return c;
00E813EE  mov         eax,dword ptr [c]  

                                                                 上面幾行程式碼中a、b、c所佔的儲存器空間應該是:(佔據棧中臨時變數區起始單元)

                                                                    b(實參):[ebp+16,ebp+13]   (這裡的ebp是esp給棧中臨時變數分配空間前的值)

                                                                    a(實參):[ebp+12,ebp+9]

                                                                    push pc  (call sum產生,佔4位元組)

                                                                    push ebp(sum函式開始部分的操作,佔4位元組)

                                                                    b(形參):[ebp,ebp-3]

                                                                    a(形參):[ebp-4,ebp-7]

                                                                    c:[ebp-8,ebp-11]

 

                                                                 從main函式 call sum 開始(包括本行),共執行了以下彙編程式碼

                                                                 main函式中呼叫sum函式的操作包括:

                                                                 mov         eax,dword ptr [b]   ;  這裡的 a b 是main函式棧內的臨時變數a b
                                                                 push        eax   ;實參入棧
                                                                 mov         ecx,dword ptr [a]  
                                                                 push        ecx    ;實參入棧 
                                                                 call        sum (0E8105Fh)   ; 本行等價於①、 push pc  ②、move pc sum地址             

}
00E813F1  pop         edi  
00E813F2  pop         esi  
00E813F3  pop         ebx  
00E813F4  mov         esp,ebp  
00E813F6  pop         ebp  
00E813F7  ret           ; pop pc
--- 無原始檔 -----------------------------------------------------------------------
00E813F8  int         3  
00E813F9  int         3  
00E813FA  int         3  
00E813FB  int         3  
00E813FC  int         3  
00E813FD  int         3  
00E813FE  int         3  
00E813FF  int         3  
--- c:\user_data\11project\practise_project\cpp\testasm\testasm\main.cpp -------

int main()
{
00E81400  push        ebp  
00E81401  mov         ebp,esp  
00E81403  sub         esp,0E4h  
00E81409  push        ebx  
00E8140A  push        esi  
00E8140B  push        edi  
00E8140C  lea         edi,[ebp-0E4h]  
00E81412  mov         ecx,39h  
00E81417  mov         eax,0CCCCCCCCh  
00E8141C  rep stos    dword ptr es:[edi]  
    int a = 2, b = 3;
00E8141E  mov         dword ptr [a],2  
00E81425  mov         dword ptr [b],3  
    int c = 0;
00E8142C  mov         dword ptr [c],0  
    c=sum(a, b);
00E81433  mov         eax,dword ptr [b]  
00E81436  push        eax  
00E81437  mov         ecx,dword ptr [a]  
00E8143A  push        ecx  
00E8143B  call        sum (0E8105Fh)  
00E81440  add         esp,8  
00E81443  mov         dword ptr [c],eax  
    return 1;
00E81446  mov         eax,1  
}
00E8144B  pop         edi  
00E8144C  pop         esi  
00E8144D  pop         ebx  
00E8144E  add         esp,0E4h  
00E81454  cmp         ebp,esp  
00E81456  call        __RTC_CheckEsp (0E8113Bh)  
00E8145B  mov         esp,ebp  
00E8145D  pop         ebp  
00E8145E  ret