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