(六)羽夏看C語言——函數


寫在前面

  此系列是本人一個字一個字碼出來的,包括示例和實驗截圖。本人非計算機專業,可能對本教程涉及的事物沒有了解的足夠深入,如有錯誤,歡迎批評指正。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閑錢,可以打賞支持我的創作。如想轉載,請把我的轉載信息附在文章后面,並聲明我的個人信息和本人博客地址即可,但必須事先通知我

你如果是從中間插過來看的,請仔細閱讀 (一)羽夏看C語言——簡述 ,方便學習本教程。

前篇答疑解惑

  答案:不會。
  解答:我相信親手做實驗的人都會知道的。

函數

  一個程序必須有一個函數,比如C語言中的main函數,也可以實現別的函數實現功能。本篇文章將從匯編的角度介紹函數,本次實驗的代碼十分簡單。為了防止干擾,請在項目屬性中關閉增量鏈接支持僅我的代碼調試(具體作用請搜索科普,它們會生成一些匯編代碼來實現相應的功能)。

int main()
{
    int a = 5;
    return 0;
}

  得到的反匯編如下:

  通過匯編可以看出,函數生成的匯編采用ebp尋址的方式。前三句匯編進行用ebp尋址的准備提棧准備緩沖區的操作,提供的緩沖區用來給函數內的局部變量用的。

  有些生成的反匯編可能是這樣的版本:

push ebp
mov ebp,esp
sub esp,0x40
push ebx
push esi
push edi
lea edi,[ebp-0x40]
mov ecx,0x10
mov eax,0xcccccccc
rep stosd

mov dword ptr [ebp-8],5
xor eax,eax

pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret

  有些人可能看不懂以下代碼:

lea edi,[ebp-0x40]
mov ecx,0x10
mov eax,0xcccccccc
rep stosd

  上面的代碼是將0xCC填充滿整個緩沖區,可幫助檢測到堆棧緩沖區溢出,這是一種常見的攻擊,威脅程序的安全性。0xCC即為我們調試的普通斷點,匯編為int 3,即VS按下F9下斷點(代碼行左邊的小紅點)。

函數調用

int test(int a, int b)
{
    return a + b;
}

int main()
{
    int a = test(1, 2);
    return 0;
}

  然后看一下反匯編:

  可以看出函數調用時會通過push傳遞參數,然后call一個地址跳轉到test函數,通過eax作為返回值。調用完畢后用add esp,8平棧,這個所謂的一種調用約定,被稱為__cdecl。當然調用約定不知這一種,你也可以自定義,不過得從匯編上實現。

調用約定

  當一個函數被調用時,函數的參數會被傳遞給被調用的函數和返回值會被返回給調用函數。函數的調用約定就是描述參數是怎么傳遞和返回值,由誰平衡堆棧,這就是所謂的調用約定。
  我們先給出常見的調用約定,其他的調用約定自行科普:

調用約定 __stdcall __cdecl __fastcall __pascal
參數傳遞順序 從右到左 從左到右 從右到左 使用寄存器和棧
平棧 調用者 子程序 子程序 子程序

  當然,在IDA中你可能會看到其他調用約定,比如__thiscall等。由於調用約定並不是我想重點講述的,具體細節自行科普。C語言默認的調用約定為__cdecl,所以在 函數調用 部分已有示例。這部分就用__fastcall做個為調用約定示例。

int __fastcall test(int a, int b)
{
    return a + b;
}

int main()
{
    int a = test(1, 2);
    return 0;
}

  如下是反匯編:

下一篇

  (七)羽夏看C語言——模板(C++)


免責聲明!

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



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