寫在前面

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

你如果是從中間插過來看的,請仔細閱讀(一)羽夏看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++)