在對函式進行除錯過程中,電腦沒有辦法知道乙個函式呼叫需要多少個、什麼樣的引數,也沒有硬體可以儲存這些引數,所以這大大的提高了對函式呼叫的準缺無誤性。
也就是說,計算機不知道怎麼給這個函式傳遞引數,傳遞引數的工作必須由函式呼叫者和函式本身來協調。為此,計算機提供了一種被稱為棧的資料結構來支援引數傳遞。棧是一種先進後出的資料結構,棧有乙個儲存區、乙個棧頂指標。棧頂指標指向堆疊中第乙個可用的資料項(被稱為棧頂)。使用者可以在棧頂上方向棧中加入資料,這個操作被稱為壓棧(push)。
壓棧以後,棧頂自動變成新加入資料項的位置,棧頂指標也隨之修改。使用者也可以從堆疊中取走棧頂,稱為彈出棧(pop),彈出棧後,棧頂下的乙個元素變成棧頂,棧頂指標隨之修改。
函式呼叫時,呼叫者依次把引數壓棧,然後呼叫函式,函式被呼叫以後,在堆疊中取得資料,並進行計算。函式計算結束以後,或者呼叫者、或者函式本身修改堆疊,使堆疊恢復原裝。
在引數傳遞中,有兩個很重要的問題必須得到明確說明: 當引數個數多於乙個時,按照什麼順序把引數壓入堆疊 函式呼叫後,由誰來把堆疊恢復原裝在高階語言中,通過函式呼叫約定來說明這兩個問題。常見的呼叫約定有: stdcall、cdecl、fastcall、thiscall、naked call
stdcall呼叫約定
stdcall很多時候被稱為pascal呼叫約定,因為pascal是早期很常見的一種教學用計算機程式語言,其語法嚴謹,使用的函式呼叫約定就是stdcall。在microsoft c++系列的c/c++編譯器中,常常用pascal巨集來宣告這個呼叫約定,類似的巨集還有winapi和callback。
stdcall的呼叫約定意味著:1)引數從右向左壓入堆疊,2)函式自身修改堆疊 3)函式名自動加前導的下劃線,後面緊跟乙個@符號,其後緊跟著引數的尺寸以上述這個函式為例,引數b首先被壓棧,然後是引數a,函式呼叫function(1,2)呼叫處翻譯成組合語言將變成:
push ebp 儲存ebp暫存器,該暫存器將用來儲存堆疊的棧頂指標,可以在函式退出時恢復mov ebp,esp 儲存堆疊指標mov eax,[ebp + 8h] 堆疊中ebp指向位置之前依次儲存有ebp,cs:eip,a,b,ebp +8指向aadd eax,[ebp + 0ch] 堆疊中ebp + 12處儲存了bmov esp,ebp 恢復esppop ebpret 8
注意不同編譯器會插入自己的彙編**以提供編譯的通用性,但是大體**如此。其中在函式開始處保留esp到ebp中,在函式結束恢復是編譯器常用的方法。從函式呼叫看,2和1依次被push進堆疊,而在函式中又通過相對於ebp(即剛進函式時的堆疊指標)的偏移量訪問引數。函式結束後,ret 8表示清理8個位元組的堆疊,函式自己恢復了堆疊。
cdecl呼叫約定
cdecl呼叫約定又稱為c呼叫約定,是c語言預設的呼叫約定,它的定義語法是: int function (int a ,int b) //不加修飾就是c呼叫約定int __cdecl function(int a,int b)//明確指出c呼叫約定
在寫本文時,出乎我的意料,發現cdecl呼叫約定的引數壓棧順序是和stdcall是一樣的,引數首先由有向左壓入堆疊。所不同的是,函式本身不清理堆疊,呼叫者負責清理堆疊。由於這種變化,c呼叫約定允許函式的引數的個數是不固定的,這也是c語言的一大特色。對於前面的function函式,使用cdecl後的彙編碼變成:
呼叫處push 1push 2call functionadd esp,8 注意:這裡呼叫者在恢復堆疊被呼叫函式_function處push ebp 儲存ebp暫存器,該暫存器將用來儲存堆疊的棧頂指標,可以在函式退出時恢復mov ebp,esp 。
儲存堆疊指標mov eax,[ebp + 8h] 堆疊中ebp指向位置之前依次儲存有ebp,cs:eip,a,b,ebp +8指向aadd eax,[ebp + 0ch] 堆疊中ebp + 12處儲存了bmov esp,ebp 恢復esppop ebpret 注意,這裡沒有修改堆疊msdn中說,該修飾自動在函式呼叫名前加前導的下劃線,因此函式名在符號表中被記錄為_function,但是我在編譯時似乎沒有看到這種變化。
AES加密方式簡析
最近了解aes加密相關,做乙個總結,希望如有不對之處,請指教 aes加密是對稱加密 128 192 256 分別表示金鑰的長度 aes的加密方式會將明文拆分成不同的塊進行加密,例如乙個256 位的資料用128的金鑰加密,則分成 明文1 128位 明文2 128位 加密密文1 128位 密文2 128...
路由選擇方式簡析
路由選擇方式簡析 典型的路由選擇方式有兩種 靜態路由和動態路由。靜態路由是在路由器中設定的固定的路由表。除非網路管理員干預,否則靜態路由不會發生變化。靜態路由不能對網路的改變作出反映.www.2cto.com 動態路由是網路中的路由器之間相互通訊,傳遞路由資訊,利用收到的路由資訊更新路由器表的過程。...
strtok函式簡析
官方的strtok函式,用來通過分隔字元 不支援字串,傳入的串中每個字元單獨當分隔符,如下例子組合的如123會處理1而23會被跳過 返回分隔的串的首位址 比如呼叫strtok abc123def 123456 返回值是指向abc的指標 下次要獲得 def 需要呼叫strtok null,123456...