Antz系統更新位址:
https://www.cnblogs.com/LexMoon/category/1262287.htmlLinux核心源碼分析位址:
https://www.cnblogs.com/LexMoon/category/1267413.htmlGithub位址: https://github.com/CasterWx
在前幾天的任務中,我們已經簡單實作了MBR,直接操作顯示器和硬碟操作來加載其他扇區的程式,如今已經可以進入保護模式了,之前一直使用的是彙編語言,接下來要使用c語言實作核心了。
0. GCC前提
gcc -c -o main.o main.c
-c的作用是編譯,彙編到目标代碼,不進行連結,也就是直接生成目标檔案。
-o的作用是将輸出的檔案以指定檔案名來存儲,有同名檔案會直接覆寫。
如果你不會使用GCC,請先去略作了解。
這行指令會生成一個main.o檔案。它隻是一個目标檔案,也是待重定位檔案,重定位是指檔案裡面所用的符号還沒有安排位址,這些符号的位址要與其他目标檔案組成一個可執行檔案時再重新定位(排位址),符号是指該目标檔案中所調用的函數或使用的變量,這裡的組成就是指連結。
main.o是可重定位檔案,ld指令可以連結,指定最終生成檔案的起始虛拟位址。
ld main.o -Ttext 0xc0001500 -e main -o main.bin
-Ttext指定了起始虛拟位址是0xc0001500,這個位址是核心加載需要的,-o是指定輸出檔案,-e是指定了程式起始位址。
1. 引入C語言
核心,是一個作業系統的核心。是基于硬體的第一層軟體擴充,提供作業系統的最基本的功能,是作業系統工作的基礎,它負責管理系統的程序、記憶體、裝置驅動程式、檔案和網絡系統,決定着系統的性能和穩定性。
現代作業系統設計中,為減少系統本身的開銷,往往将一些與硬體緊密相關的(如中斷處理程式、裝置驅動程式等)、基本的、公共的、運作頻率較高的子產品(如時鐘管理、程序排程等)以及關鍵性資料結構獨立開來,使之常駐記憶體,并對他們進行保護。通常把這一部分稱之為作業系統的核心。
程式可以直接地被調入計算機中執行,這樣的設計說明了設計者不希望提供任何硬體抽象和作業系統的支援,它常見于早期計算機系統的設計中。最終,一些輔助性程式,例如程式加載器和調試器,被設計到機器核心當中,或者固化在隻讀存儲器裡。這些變化發生時,作業系統核心的概念就漸漸明晰起來了。
antz_os.asm :
1 ; antz_os
2
3
4 BOTPAK EQU 0x00280000
5 DSKCAC EQU 0x00100000
6 DSKCAC0 EQU 0x00008000
7
8
9 CYLS EQU 0x0ff0
10 LEDS EQU 0x0ff1
11 VMODE EQU 0x0ff2
12 SCRNX EQU 0x0ff4
13 SCRNY EQU 0x0ff6
14 VRAM EQU 0x0ff8
15
16 ORG 0xc200
17
18
19
20 MOV AL,0x13
21 MOV AH,0x00
22 INT 0x10
23 MOV BYTE [VMODE],8
24 MOV WORD [SCRNX],320
25 MOV WORD [SCRNY],200
26 MOV DWORD [VRAM],0x000a0000
27
28
29
30 MOV AH,0x02
31 INT 0x16 ; keyboard BIOS
32 MOV [LEDS],AL
33
34
35
36
37
38
39 MOV AL,0xff
40 OUT 0x21,AL
41 NOP
42 OUT 0xa1,AL
43
44 CLI
45
46
47
48 CALL waitkbdout
49 MOV AL,0xd1
50 OUT 0x64,AL
51 CALL waitkbdout
52 MOV AL,0xdf ; enable A20
53 OUT 0x60,AL
54 CALL waitkbdout
55
56 ; 保護模式轉換
57
58 [INSTRSET "i486p"]
59
60 LGDT [GDTR0]
61 MOV EAX,CR0
62 AND EAX,0x7fffffff
63 OR EAX,0x00000001
64 MOV CR0,EAX
65 JMP pipelineflush
66
67 MOV AX,1*8
68 MOV DS,AX
69 MOV ES,AX
70 MOV FS,AX
71 MOV GS,AX
72 MOV SS,AX
73
74
75
76 MOV ESI,bootpack ; 源
77 MOV EDI,BOTPAK ; 目标
78 MOV ECX,512*1024/4
79 CALL memcpy
80
81
82
83
84
85 MOV ESI,0x7c00 ; 源
86 MOV EDI,DSKCAC ; 目标
87 MOV ECX,512/4
88 CALL memcpy
89
90
91
92 MOV ESI,DSKCAC0+512 ; 源
93 MOV EDI,DSKCAC+512 ; 目标
94 MOV ECX,0
95 MOV CL,BYTE [CYLS]
96 IMUL ECX,512*18*2/4
97 SUB ECX,512/4
98 CALL memcpy
99
100
101
102
103
104
105 MOV EBX,BOTPAK
106 MOV ECX,[EBX+16]
107 ADD ECX,3
108 SHR ECX,2
109 JZ skip
110 MOV ESI,[EBX+20]
111 ADD ESI,EBX
112 MOV EDI,[EBX+12]
113 CALL memcpy
114 skip:
115 MOV ESP,[EBX+12]
116 JMP DWORD 2*8:0x0000001b
117
118 waitkbdout:
119 IN AL,0x64
120 AND AL,0x02
121 JNZ waitkbdout
122 RET
123
124 memcpy:
125 MOV EAX,[ESI]
126 ADD ESI,4
127 MOV [EDI],EAX
128 ADD EDI,4
129 SUB ECX,1
130 JNZ memcpy
131 RET
132
133
134 ALIGNB 16
135 GDT0:
136 RESB 8
137 DW 0xffff,0x0000,0x9200,0x00cf
138 DW 0xffff,0x0000,0x9a28,0x0047
139 DW 0
140 GDTR0:
141 DW 8*3-1
142 DD GDT0
143
144 ALIGNB 16
145 bootpack:
bootpack.c:
1 void io_hlt(void);
2 void write_mem8(int addr,int data);
3
4 void HariMain(void)
5 {
6 int i ;
7 for(i=0xa0000;i<0xaffff;i++){
8 write_mem8(i,15);
9 }
10 for(;;){
11 io_hlt();
12 }
13 }
func.asm:
1 [FORMAT "WCOFF"]
2 [BITS 32]
3 [INSTRSET "i486p"]
4
5 [FILE "naskfunc.nas"]
6
7 GLOBAL _io_hlt
8
9 [SECTION .text]
10
11 _io_hlt: ; void io_hlt(void);
12 HLT
13 RET
14
15 _write_mem8:
16 MOV ECX,[ESP+4]
17 MOV AL,[ESP+8]
18 MOV [ECX],AL
19 RET
在func.asm中聲明了bootpack.c中調用的函數,用于繪制螢幕,如果你還不了解怎麼繪制螢幕,可以看看第三天的直接操作顯示卡部分。
生成的img打開在虛拟機之後。
看到這裡你可能會發現,我們在c語言中定義的函數完成了螢幕繪制,在HariMain函數中的for循環将整個螢幕完成了繪制。write_mem8函數的兩個參數分别控制了位置和顔色,這是圖形化的一大步。
随意修改一下參數之後,螢幕顯示就是不一樣的顔色了,至于怎麼改,可以在for循環裡面自行修改了。
關于核心的知識便不再向之前一樣詳細概況了,推薦一本書,《Linux核心完全剖析》。