作業系統啟動的過程

_Elysia發表於2024-06-27

目錄
  • 作業系統,啟動!
    • 大致過程
    • 重要程式
      • bootsect.s
      • setup.s
      • head.s

作業系統,啟動!

大致過程

​ 計算機的工作方式是取指執行,而執行其的前提是記憶體中有程式碼。作業系統剛開始並不是在記憶體中,而是在磁碟上,因此第一步需要將其以一定的方式從磁碟讀入記憶體。

(1)x86PC剛開機時CPU處於真實模式(和保護模式對應),定址方式為CS左移四位+IP

(2)開機時,CS = 0xFFFF;IP = 0X0000

(3)定址0xFFFF0(ROM BIOS對映區)

開機時記憶體中唯一有程式碼的地方

(4)檢查RAM,鍵盤,顯示器,軟硬磁碟

(5)將磁碟0磁軌0扇區(引導扇區,作業系統的第一段程式碼bootsect.s)讀入0x7c00處

一個扇區512位元組

.s 彙編程式碼

(6)設定cs = 0x7c0,ip = 0x0000

以下摘自《Linux核心完全註釋》

​ 這裡先總的說明一下 Linux 作業系統啟動部分的主要執行流程。當 PC 的電源開啟後,80x86 結構的 CPU 將自動進入真實模式,並從地址 0xFFFF0 開始自動執行程式程式碼,這個地址通常是 ROM-BIOS 中的 地址。PC 機的 BIOS 將執行某些系統的檢測,並在實體地址 0 處開始初始化中斷向量。此後,它將可啟 動裝置的第一個扇區(磁碟引導扇區,512 位元組)讀入記憶體絕對地址 0x7C00 處,並跳轉到這個地方。啟 動裝置通常是軟碟機或是硬碟。這裡的敘述是非常簡單的,但這已經足夠理解核心初始化的工作過程了。
​ Linux 的最最前面部分是用 8086 組合語言編寫的(boot/bootsect.s),它將由 BIOS 讀入到記憶體絕對地 址 0x7C00(31KB)處,當它被執行時就會把自己移到絕對地址 0x90000(576KB)處,並把啟動裝置中後 2kB 位元組程式碼(boot/setup.s)讀入到記憶體 0x90200 處,而核心的其它部分(system 模組)則被讀入到從地址 0x10000 開始處,因為當時 system 模組的長度不會超過 0x80000 位元組大小(即 512KB),所以它不會覆 蓋在 0x90000 處開始的 bootsect 和 setup 模組。後面 setup 程式將會把 system 模組移動到記憶體起始處,這 樣 system 模組中程式碼的地址也即等於實際的實體地址,便於對核心程式碼和資料的操作。圖 3-1 清晰地顯 示出 Linux 系統啟動時這幾個程式或模組在記憶體中的動態位置。其中,每一豎條框代表某一時刻記憶體中各程式的映像位置圖。在系統載入期間將顯示資訊"Loading..."。然後控制權將傳遞給 boot/setup.s 中的代 碼,這是另一個真實模式組合語言程式。

重要程式

bootsect.s

.globl begtext,begdata,begbss,endtext,enddata,endbss
.text	//文字段
begtext:
.data	//資料段
begdata:
.bss	//未初始化資料段
begbss:
entry start	//關鍵字entry告知連結器,程式從start標號開始執行
start:
	mov ax, #BOOTSEG	//將ds段暫存器置為0x07c0
	mov ds, ax
	mov ax, #INITSEG	//將es段暫存器置為0x9000
	mov es, ax
	mov cx, #256		//移動計數值=256字
	sub si, si			//源地址	ds:di = 0x07c0:0x0000
	sub di, di			//目標地址	es:si = 0x9000:0x0000
	rep
	movw
	jmpi go, INITSEG	//間接跳轉,cs=0x9000,ip=go
	
go:	mov ax, cs			//cs=0x9000
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov sp, #0xFF00		//由於程式碼移動過了,所以要重新設定堆疊段的位置。sp只要指向遠大於512偏移(即地址0x90200)處都可以。因為從0x90200地址開始處還要放置setup程式,而此時setup程式大約為4個扇區,因此sp要指向大於(0x200+0x200*4+堆疊大小)處
	
load_setup:
	mov dx, #0x0000
	mov cx, #0x0002
	mov bx, #0x0200
	mov ax, #0x0200+SETUPLEN
	int 0x13			//利用BIOS中斷INT 0x13將setup模組從磁碟第二個扇區開始讀到0X90200處,共讀4個扇區。如果讀出錯,則復位驅動器,並重試
	jnc ok_load_setup
	mov dx, #0x0000
	mov ax, #0x0000	//復位
	int 0x13
	j load_setup	//重讀
	
ok_load_setup:
	mov dl, #0x00
	mov ax, #0x0800
	int 0x13
	mov ch, #0x00
	seg cs
	mov sectors, cx
	mov ah, #0x03		//顯示一些資訊('Loading system...'共24個字元)
	xor bh, bh		//讀游標位置
	int 0x10
	mov cx, #24		//共24個字元
	mov bx, #0x0007	//顯示屬性
	mov bp, #msg1	//指向要顯示的字串
	mov ax, #0x1301
	int 0x10		//顯示字元
	mov ax, #STSSEG		//0x1000
	mov es, ax
	call read_it		//讀入system模組
	jmpi 0, SETUPSEG	//跳轉到0x9020:0000(setup.s程式的開始處)

setup.s

head.s

相關文章