库与运行库
内存


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内核的系统调用都包装了起来,而且其导出函数对于应用程序开发者是不公开的,原则上应用程序不该该直接使用其中的任何导出函数。