庫與運行庫
內存
edi = ebp - 0xC0;
ecx = 0x30;
eax = 0xCCCCCCCC;
for (; ecx != 0; --ecx, edi+=4)
*((int*)edi) = eax;
- 函數將返回值存儲在eax中,返回後的函數的調用方在讀取eax。對於返回5~8字節對象的狀況,幾乎全部的調用慣例都是採用eax和edx聯合返回的方式進行的。若是返回值類型的尺寸太大,以下圖所示,C語言的函數返回時會使用一個臨時的棧上內存區域做爲中轉,結果返回值對象會被拷貝兩次。於是不到萬不得已,不要輕易返回大尺寸的對象。
- 一個普通的Windows進程的地址空間分佈能夠如圖所示。
- Windows系統提供了一個API叫作VirtualAlloc(),用來向系統申請空間,它與Linux下的mmap很是類似。實際上VirtualAlloc()申請的空間不必定只用於堆,它僅僅是向系統預留了一塊虛擬地址,應用程序能夠按照須要隨意使用。可是,使用VirtualAlloc()函數申請空間時,系統要求空間大小必須爲頁的整數倍,即對於x86系統來講,必須是4096字節的整數倍。這就是操做系統的「批發」內存的接口函數了,4096字節起批。
- 在Windows中,堆管理器提供了一套與堆相關的API能夠用來建立(HeapGreate)、分配(HeapAlloc)、釋放(HeapFree)和銷燬(HeapDestroy)堆空間。其中,HeapGreate就是經過VirtualAlloc()來實現向操做系統批發一塊內存空間。堆管理器經過這些API實現了堆分配算法。
- 咱們常用的malloc函數其實是運行庫提供的函數。它其實是堆Heapxxxx系列函數的封裝,當一個堆空間不夠時,它會在進程中建立額外的堆。
- 堆分配算法實際上就是解決如何管理一大塊連續的內存空間,可以按照需求分配、釋放其中的空間的題。堆分配算法有不少種,例如簡單的空閒列表算法、位圖算法、對象池算法等,也有很複雜、適用於某些高性能或者其餘特殊要求的場合。實際上不少現實應用中,堆的分配算法每每是採用多種算法複合而成的。
運行庫
系統調用與API
- 爲了讓應用程序有能力訪問系統資源,也爲了讓程序藉助操做系統作一些必須由操做系統支持的行爲,每一個操做系統都會提供一套接口,以供應用程序使用。這些接口每每經過中斷來實現,好比Linux使用0x80號中斷做爲系統調用的入口,Windows採用0x2E號中斷做爲系統調用入口。
- 中斷通常具備兩種屬性,一個稱爲中斷號(從0開始),一個稱爲中斷處理程序(Interrupt Service Routine,ISR)。不一樣的中斷具備不一樣的中斷號,而同時一箇中斷處理程序一一對應一箇中斷號。在內核中,有一個數組稱爲中斷向量表(Interrupt Vector Table),這個數組的第n項包含了指向第n號中斷的中斷處理程序的指針。當中斷到來時,CPU會暫停當前執行的代碼,根據中斷的中斷號,在中斷向量表中找到對應的中斷處理程序,並調用它。中斷處理程序執行完成以後,CPU會繼續執行以前的代碼。一個簡單的示意圖以下:
- 因爲中斷號是頗有限的,操做系統不會捨得用一箇中斷號來對應一個系統調用,而更傾向於用一個或少數幾個中斷號來對應全部的系統調用。那麼,對於同一個中斷號,操做系統如何知道是哪個系統調用要被調用呢?和中斷同樣,系統調用都有一個系統調用號,這個系統調用號一般就是系統調用在系統調用表中的位置。以Linux的0x80中斷爲例,系統調用號是由eax傳入的。用戶將系統調用號放入eax,而後使用0x80調用中斷,中斷服務程序就能夠從eax中取得系統調用號,進而調用對應的函數。下面是以fork爲例的Linux系統調用的執行流程。
- 不少操做系統是以系統調用做爲應用程序最底層的,而Windows的最底層接口是Windows API。Windows API是Windows編程的基礎,儘管Windows的內核提供了數百個系統調用(Windows又把系統調用稱做系統服務),可是出於種種緣由,微軟並無將這些系統調用公開,而在這些系統調用之上,創建了這樣一個API層,讓程序員只能調用API層的函數,而不是如Linux通常直接使用系統調用。Windows在加入API層之後,一個普通的fwrite()的調用路徑如圖:
- Windows API是以DLL導出函數的形式暴露給應用程序開發者的。微軟把這些Windows API DLL導出函數的聲明的頭文件、導出庫、相關文件和工具一塊兒提供給開發者,並讓它們稱爲Software Development Kit(SDK)。當咱們安裝了Visual Studio後,能夠在SDK的安裝目錄下找到全部的Windows API函數聲明。其中有一個頭文件「Windows.h」包含了Windows API的核心部分,只要咱們在程序裏面包含了它,就可使用Windows API的核心部分了。
- 在Windows NT系列的平臺上,系統的DLL在實現上都會依賴一個更爲底層的DLL,叫作NTDLL.DLL,由它來進行系統調用,NTDLL.DLL把Windows NT內核的系統調用都包裝了起來,而且其導出函數對於應用程序開發者是不公開的,原則上應用程序不該該直接使用其中的任何導出函數。