這不是一個真實的操作系統。這只是一個簡單的操作系統,以教育目的創建。
我關注的主要目標是了解OS如何從頭開始工作。從自己的引導扇區開始,硬件和軟件中斷,自己的驅動程序。
存儲庫的後綴加上GCC,因為我打算編寫另一個帶有Rust的簡單操作系統。因此,我希望,將會有Ghaiklor-OS-GCC和Ghaiklor-OS-Rustc 。
| 你好世界 |
|---|
Ghaiklor-OS-GCC由兩個原始二進制格式的文件組成: boot.bin和kernel.bin 。它們位於boot/boot.bin和kernel/kernel.bin中。
boot.bin是通過nasm編譯的。 MakeFile接管boot/boot.asm並調用nasm boot/boot.asm -f bin -o boot/boot.bin 。 NASM手柄包括子文件夾本身,因此所有彙編文件都將彙編為二進製文件。沒有別的,簡單。
kernel.bin是通過交叉補充GCC和LD編譯的,您必須安裝。看看開發環境部分。安裝交叉補償器後,我們可以從CPU ,驅動程序,包括內核和LIBC文件夾中獲取來源。所有.c文件均通過gcc編譯。編譯的對象文件用於編譯內核。然後通過LD -LD ld -o kernel/kernel.bin -Ttext 0x1000 <OBJ_FILES> --oformat binary 。
os-image.bin是編譯boot.bin和kernel.bin的助理。 cat boot/boot.bin kernel/kernel.bin > os-image.bin 。
我寫了bootstrap.sh腳本,您可以運行。它將為您的主機計算機安裝所有所需的依賴項。
bash bootstrap.sh當計算機打開或重置計算機時,它會通過一系列稱為Post-Power-onsef-Seft-pest的診斷。該序列最終導致定位可引導設備,例如軟盤,CDROM或硬盤。
如果設備分別在字節511和512中帶有字節序列0x55 0xAA則可以引導。當BIOS找到這樣的引導扇區時,將其加載到0x0000:0x7C00的內存中。
可引導設備的簡單實現:
jmp $
times 510 - ($ - $$) db 0
dw 0xAA55 $ - $$在CURRENT_POINTER - START_POINTER 。這樣,我們正在計算引導記錄的時間。之後,我們從中獲得510,並填充零,並獲得帶有引導扇區簽名的512字節啟動記錄。
例如,我們的$ - $$等於100。因此,我們有510 - 100 = 410免費字節。我們用零填充這410個字節。最後兩個字節511和512是可引導的簽名,我們用dw 0xAA55填充。
完畢!我們擁有可引導設備,可以用您喜歡的任何代碼替換jmp $ 。
引導部門實現
在開始時,我們的代碼正在實際模式下運行。
實際模式是所有X86處理器上都存在的簡單16位模式。實際模式是第一個X86模式設計,並被許多早期操作系統使用。出於兼容目的,所有X86處理器都以實際模式開始執行。
在實際模式下有什麼好壞?
缺點
優點
由於實際模式存在許多局限性和問題,我們需要切換到受保護的模式。
自80286以來,受保護模式是現代英特爾處理器的主要操作模式。它允許使用多個虛擬地址空間,每個地址空間最多具有4 GB的可尋址內存。
由於由BIOS初始化的CPU以實際模式開始,因此切換到受保護模式可防止您使用大多數BIOS中斷。在切換到受保護模式之前,您必須禁用中斷,包括NMI,啟用A20線並加載全局描述符表。
用於切換到受保護模式的算法:
cli
lgdt [ gdt_descriptor ]
mov eax , cr0
or eax , 0x1
mov cr0 , eax
jmp CODE_SEG:init_pm切換到PM的實現
全局描述符表
但是,我們可以走得更遠...
什麼是長模式,為什麼要設置它?
由於引入了X86-64處理器,也引入了新模式,稱為長模式。長模式基本上是由兩種次模式組成的,分別是實際的64位模式和兼容模式(32位)。
我們感興趣的只是64位模式,因為此模式提供了許多新功能,例如:
在切換到遠程模式之前,我們必須檢查CPU是否支持此模式。如果CPU不支持延長模式,我們需要退縮到受保護的模式。
檢測長度模式是否支持
如果是這樣,請切換到長模式
所有這些模式都很棒,但是我們不能在512字節中編寫操作系統。因此,我們的引導部門必須知道如何從硬盤加載我們的編譯內核。
當我們處於實際模式時,我們可以使用BIOS中斷從磁盤中讀取。在我們的情況下,是INT 13,2 - Read Disk Sectors 。
如何使用它?
;; al = number of sectors to read (1 - 128)
;; ch = track/cylinder number
;; cl = sector number
;; dh = head number
;; dl = drive number
;; bx = pointer to buffer
mov ah , 0x02
mov al , 15
mov ch , 0x00
mov cl , 0x02
mov dh , 0x00
mov dl , 0
mov bx , KERNEL_OFFSET_IN_MEMORY
int 0x13該代碼導致從硬盤讀取到地址KERNEL_OFFSET_IN_MEMORY 。它讀取從第二個部門開始,然後通過地址KERNEL_OFFSET_IN_MEMORY存儲它。
由於我們的編譯OS映像是引導扇區和內核的串聯,並且我們知道我們的引導扇區為512字節,因此我們可以肯定的是,我們的內核始於第二扇區。
成功完成閱讀時,我們可以通過我們的KERNEL_OFFSET_IN_MEMORY撥打指令,並對內核進行執行。
call KERNEL_OFFSET_IN_MEMORY
jmp $磁盤的實現
我們可以在此處繪製有關引導部門的線路。流很簡單:
call指令對內核進行執行;在此步驟中,我們的引導部門完成了工作,並開始與內核合作。
您可以通過引導源導航,並嘗試獲取其工作原理。
當我們通過地址調用指令時,我們可能會遇到一些問題。我們不確定,通過地址的指令是kernel_main() 。解決方案很簡單。
我們可以編寫一個附加在內核代碼開始的子例程。我們的內核kernel_main()的該子例程呼叫的外部功能。當將對象文件鏈接在一起時,此調用將轉換為我們的kernel_main()的呼叫。
global _start
[bits 32]
[extern kernel_main]
_start:
call kernel_main
jmp $內核輸入實現
在此步驟中,我們對kernel_main()方法有一個入口點。這就是我們整個內核的入口點。
我認為,很無聊地解釋了#include工作原理以及我們的kernel_main()中發生了什麼。您可以輕鬆地遵循我從中調用的方法。
c中的內核條目
那是最簡單的部分。
我們需要以原始二進制格式構建boot/boot.bin圖像。為此,我們將帶有特殊標誌的nasm彙編器稱為。
nasm boot/boot.asm -f bin -o boot/boot.bin它會導致您可以通過QEMU運行的原始二進制格式。
在此步驟中,我們已經有效編譯了引導扇區。
除了boot文件夾外,我們還需要從所有文件夾中構建所有源。
所有C文件均通過gcc和Assembly Files通過nasm編譯為對象文件:
gcc -g -ffreestanding -Wall -Wextra -fno-exceptions -m32 -std=c11 -c < SOURCE > -o < OBJ_FILE >
nasm < SOURCE > -f elf -o < OBJ_FILE >它導致所有需要的對象文件鏈接到原始二進制格式。剩下要做的就是通過ld將它們鏈接在一起:
ld -o kernel/kernel.bin -Ttext 0x1000 kernel/kernel_entry.o < OBJ_FILES > --oformat binary請注意, kernel/kernel_entry.o首先是呼叫kernel_main()問題。這樣,我們保證將從我們的boot/kernel_entry.asm中調用第一個指令。
畢竟,我們以原始二進制格式編譯了內核圖像。
由於我們的引導扇區和內核是原始的二進制格式,因此我們可以將它們串聯。
cat boot/boot.bin kernel/kernel.bin > os-image.bin現在,我們可以通過qemu-system-i386運行os-image.bin 。 BIOS試圖找到可引導扇區,找出我們的boot/boot.bin並看到簽名。開始在boot/boot.bin上執行我們的彙編代碼,該代碼將我們的kernel/kernel.bin通過int 13,2加載到內存中並執行。
這就是一起工作的方式。隨時可以通過該項目導航,謝謝?
麻省理工學院許可證(MIT)
版權(C)2016 Eugene Obrezkov
特此免費授予獲得此軟件副本和相關文檔文件副本(“軟件”)的任何人,以無限制處理該軟件,包括無限制的使用權,複製,複製,修改,合併,合併,發布,分發,分發,分發,訂婚,和/或允許軟件的副本,並允許對以下條件提供以下條件,以下是以下條件。
上述版權通知和此許可通知應包含在軟件的所有副本或大量部分中。
該軟件是“原樣”提供的,沒有任何形式的明示或暗示保證,包括但不限於適銷性,特定目的的適用性和非侵權的保證。在任何情況下,作者或版權持有人都不應對任何索賠,損害賠償或其他責任責任,無論是在合同,侵權的訴訟中還是其他責任,是由軟件,使用或與軟件中的使用或其他交易有關的。