FILE_01:mbr.asm
1)mbr, Master Boot Record,512字節,位於0x7c00
2)將loader從磁盤讀取到內存中,並跳轉到loader
function: read_hard_disk_0
======================================================================
FILE_02:loader.asm
1)調用BIOS中斷0x15獲取內存大小
2)進入保護模式:
>> 2-1 構建全局描述符表GDT(gdt的第0項不可用),lgdt加載基地址和界限值;
>> 2-2 打開地址線A20,否則還是隻能訪問1MB內存(實模式下,只能使用20根地址線);
>> 2-3 將控制寄存器CR0的PE位置1(Protection Enable),清空流水線、重新加載段寄存器。
3)將kernel從磁盤讀取到內存中(這裏爲了簡單,選擇了在開啓分頁之前加載)
4)開啓分頁機制:
>> 4-1 創建頁目錄PD和頁表PT(每頁4KB);低3G爲用戶空間、高1G爲內核空間;gdt也已位於內核空間,重新lgdt;
>> 4-2 將控制寄存器CR3賦值爲頁目錄表基地址;
>> 4-3 將控制寄存器CR0的PG位置1(Page位);從此,段部件產生的地址就不再被看成物理地址,而是要送往頁部件進行變換,以得到真正的物理地址。
5)解析kernel的ELF,並跳轉過去(跳轉地址爲編譯C代碼時指定的地址)。
將ELF文件中的段segment拷貝到各段自己被編譯的虛擬地址處,將這些段單獨提取到內存中,這就是所謂的內存中的程序映像。
function: read_hard_disk_0; setup_page創建頁目錄及頁表;kernel_init解析內核ELF;mem_cpy逐字節拷貝
======================================================================
FILE_03:main.c
C語言代碼:while(1);
// gcc -m32 -I lib/ -c -o main.o main.c
// ld -m elf_i386 -Ttext 0xc0001500 -e main -o kernel.bin main.o lib/print.o
======================================================================
FILE_04:print.asm
用匯編實現打印函數,供C語言調用。
put_char,打印一個字符,該字符通過棧傳入
put_str,打印字符串,字符串首地址通過棧傳入,逐字節讀取字符串並壓入棧,調用put_char
put_int,以十六進制形式打印32位二進制數
======================================================================
GITHUB:https://github.com/trb331617/os_elephant/tree/master/chapter_6
運行截圖: