接上一篇
kernel.img由startup.S以及一堆c文件編譯而成。這是一個ELF格式的文件。(其實前面的boot.img、 diskboot.img、lzma_decomPRess.img本來也都是ELF格式文件,但是經(jīng)過了精簡。)
kernel.img鏈接時,目標(biāo)裝載地址是0x9000,這是在Makefile.core.dep中定義的:
i386_pc_ldflags= '$(TARGET_IMG_BASE_LDOPT),0x9000';
但是現(xiàn)在kernel.img被加載到了0x100000,startup.S里的代碼開始執(zhí)行。所以開頭的幾個指令首先是把startup_raw.S中通過寄存器傳過來的幾個參數(shù)保存起來,然后就立即把kernel.img代碼段開頭到數(shù)據(jù)段結(jié)尾(_edata)從0x100000復(fù)制到0x9000開始的內(nèi)存區(qū)域,接著一個跳轉(zhuǎn):
jmp *%esi /* LOCAL(cont): */
巧妙地跳到了復(fù)制后代碼的地址,接下去代碼執(zhí)行應(yīng)該就變正常了。
然后對bss段進(jìn)行清0,并對存放在bss段的grub_boot_device賦值。bss段(Block Started by Symbol)存放的是未初始化的符號(變量)。通常一個程序執(zhí)行前要對bss進(jìn)行清0,這樣未初始化的符號值默認(rèn)為0。這項工作由GRUB自己完成。
接著執(zhí)行:
call EXT_C(grub_main)/* void grub_main (void) __attribute__ ((noreturn)); */
這是在一個c文件kern/main.c中的函數(shù),也就是GRUB kernel的主函數(shù)。grub_main不會返回,于是這條指令相當(dāng)于一個跳轉(zhuǎn)。
至此startup.S的代碼執(zhí)行完畢。
|
新聞熱點
疑難解答