從零實現一個操作系統-day4-5

我的博客startcraft.cn

在軟盤中安裝grub

昨天在這一步出了點問題,很難受,今天來解決一下
我發現問題可能跟我使用的是騰訊雲的vps有關,後來我換了一臺vultr的centos的vps之後就沒問題了,接着昨天的
用loop0把floppy.img虛擬成塊設備

sudo losetup /dev/loop0 floppy.img

進入grub命令行

sudo grub

然後輸入下面的命令

device (fd0) /dev/loop0
root (fd0)
setup (fd0)

然後解除loop0和floppy.img的關聯,解除掛載

sudo losetup -d /dev/loop0
sudo umount /mnt/kernel

現在軟盤鏡像就做好了,不過還沒有內核,先來測試一下

qemu -fda floppy.img -boot a

看到grub的菜單界面就成功了

注意:如果用的是vps,那麼ssh客戶端一定要支持x11,不然虛擬機運行不了,因爲虛擬機需要圖形化界面,今天grub命令行和x11花了我大量的時間,摸索Google了半天,總算解決了2333,所以昨天就沒更新bolg,內容太少了233

內核的入口

boot/boot.s

; ----------------------------------------------------------------
;
; boot.s -- 內核從這裏開始
;
; ----------------------------------------------------------------

; Multiboot 魔數,由規範決定的
MBOOT_HEADER_MAGIC equ 0x1BADB002

; 0 號位表示所有的引導模塊將按頁(4KB)邊界對齊
MBOOT_PAGE_ALIGN equ 1 << 0

; 1 號位通過 Multiboot 信息結構的 mem_* 域包括可用內存的信息
; 告訴(把內存空間的信息包含在信息結構中GRUBMultiboot)
MBOOT_MEM_INFO equ 1 << 1

; 定義我們使用的 Multiboot 的標記
MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO

; 域是一個位的無符號值,當與其他的域checksum32magic也就是(和magicflags)
; 相加時,要求其結果必須是位的無符號值32 0 即(magic+flags+checksum = 0)
MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC+MBOOT_HEADER_FLAGS)

; 符合規範的Multiboot OS 映象需要這樣一個 magic Multiboot 頭
; Multiboot 頭的分佈必須如下表所示:
; ----------------------------------------------------------
; 偏移量類型域名備註
;
; 0 u32 magic 必需
; 4 u32 flags 必需
; 8 u32 checksum 必需
;
; 我們只使用到這些就夠了,更多的詳細說明請參閱 GNU 相關文檔
;-----------------------------------------------------------

;-----------------------------------------------------------------------------

[BITS 32] ; 所有代碼以 32-bit 的方式編譯
section .text ; 代碼段從這裏開始

; 在代碼段的起始位置設置符合 Multiboot 規範的標記

dd MBOOT_HEADER_MAGIC ; GRUB 會通過這個魔數判斷該映像是否支持
dd MBOOT_HEADER_FLAGS ; GRUB 的一些加載時選項,其詳細註釋在定義處
dd MBOOT_CHECKSUM ; 檢測數值,其含義在定義處

[GLOBAL start] ; 向外部聲明內核代碼入口,此處提供該聲明給鏈接器
[GLOBAL glb_mboot_ptr] ; 向外部聲明 struct multiboot * 變量
[EXTERN kern_entry] ; 聲明內核 C 代碼的入口函數

start:
cli ; 此時還沒有設置好保護模式的中斷處理,要關閉中斷
; 所以必須關閉中斷
mov esp, STACK_TOP ; 設置內核棧地址
mov ebp, 0 ; 幀指針修改爲 0
and esp, 0FFFFFFF0H ; 棧地址按照字節對齊16
mov [glb_mboot_ptr], ebx ; 將 ebx 中存儲的指針存入全局變量
call kern_entry ; 調用內核入口函數
stop:
hlt ; 停機指令,可以降低 CPU 功耗
jmp stop ; 到這裏結束,關機什麼的後面再說

;-----------------------------------------------------------------------------

section .bss ; 未初始化的數據段從這裏開始
stack:
resb 32768 ; 這裏作爲內核棧
glb_mboot_ptr: ; 全局的 multiboot 結構體指針
resb 4

STACK_TOP equ $-stack-1 ; 內核棧頂,$ 符指代是當前地址

;-----------------------------------------------------------------------------

上面這段是彙編的代碼,分號後面的是註釋
7-22行定義了Multiboot規範要用到的一些值,Multiboot定義的Multiboot 頭的分佈必須如下表所示:

偏移量 類型 域名 備註
0  u32  magic  必需
4  u32  flags  必需
8  u32  checksum  必需
12  u32  header_addr  如果flags[16]被置位
16  u32  load_addr  如果flags[16]被置位
20  u32  load_end_addr  如果flags[16]被置位
24  u32  bss_end_addr  如果flags[16]被置位
28  u32  entry_addr  如果flags[16]被置位
32  u32  mode_type  如果flags[2]被置位
36  u32  width  如果flags[2]被置位
40  u32  height  如果flags[2]被置位
44  u32  depth  如果flags[2]被置位

這裏只用到了前三個,MBOOT_HEADER_MAGIC 就是標誌頭的魔數,必須等於0x1BADB002
MBOOT_HEADER_FLAGS 就是flag,一共32位,不同位置1有不同的含義,這裏將0和1位置1了,代表的意義在註釋上
MBOOT_CHECKSUM 就是checksum ,域checksum是一個32位的無符號值,當與其他的magic域(也就是magic和flags)相加時,結果必須是32位的無符號值0(即magic + flags + checksum = 0)。
43-45行定義了這三個數爲32位,即4字節
51行的start就是鏈接器腳本定義的內核入口函數
start乾的事情就是關中斷,設置棧,然後將grub提供的信息的指針放到全局變量裏面((按照協議,GRUB把一些計算機硬件和我們內核文件相關的信息放在了一個結構
體中,並且將這個結構體指針放在了ebx寄存器中)
最後調用c語言寫的函數kern_entry,這個函數返回後就是hlt待機了
65行到最後定義了未初始化的一些空間,定義了棧大小爲32768字節,glb_mboot_ptr指針爲4字節,定義了棧頂的地址

init/entry.c

彙編寫完了,現在可以來寫c語言啦

int kern_entry()
{
	return 0;
}

這個就是上面彙編調用的c的函數,函數啥也沒幹233

include/types.h

#ifndef INCLUDE_TYPES_H_
#define INCLUDE_TYPES_H_

#ifndef NULL
#define NULL 0
#endif

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef char int8_t;

#endif // INCLUDE_TYPES_H_

這個就是做了一些宏定義,並且把c語言的一些類型名字做了重命名
現在的目錄結構是這樣的:

現在我們來啓動試試看

make 
make qemu

先看到grub的菜單,然後選擇操作系統之後就啥也不幹了,畢竟我們啥也沒寫233
今天就先結束了,成完成了一個啥也不做的內核2333

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章