最开始的是loadros.asm,它会将ntoskrnl.exe等各个模块读入内存,并跳到0:901000。同时它还会初始化一个_LOADER_PARAMETER_BLOCK数据结构。
typedef struct _LOADER_PARAMETER_BLOCK
{ ULONG Flags; ULONG MemLower; ULONG MemHigher; ULONG BootDevice; ULONG CommandLine; ULONG ModsCount; ULONG ModsAddr; UCHAR Syms[12]; ULONG MmapLength; ULONG MmapAddr; ULONG DrivesCount; ULONG DrivesAddr; ULONG ConfigTable; ULONG BootLoaderName; } LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK; 并且初始化_LOADER_MODULE数据结构的数组,每个pe文件对应一个。 typedef struct _LOADER_MODULE { ULONG ModStart; ULONG ModEnd; ULONG String; ULONG Reserved; } LOADER_MODULE, *PLOADER_MODULE; 通过跳转0:901000,来到ntoskrnl.exe的_NtProcessstartup模块,它是一段16位的代码。初始化页目录、页表。初始化GDT、IDT。最后跳到main.c中的_main函数。 _main将bootloader中得到信息进一步处理。例如bootloader是将各个模块读入到低端内存,而经过分页后,ntoskrnl.exe被应设在0xc0000000的位置。重新修改LOADER_PARAMETER_BLOCK结构和LOADER_MODULE结构的信息。 然后调用LdrSafePEProcessModule,将ntoskrnl.exe hal.sys重定向内存。 最后调用KiSystemStartup