青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-80  評論-24  文章-0  trackbacks-0
為了盡快進入內核,并沒有讓loader做太多工作,它的工作其實主要有三項:
1、保存一些系統參數,如光標位置、擴展內存大小、顯示模式、顯存大小以及硬盤參數等等
2、將內核移動到指定位置,這里移動到0x0起始的位置
3、切換進入保護模式
還是先貼代碼:

  1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2 ; 該文件主要作用是獲取一些系統參數,將參數保存在0xf000:0x0的位置,然后準備gdt,
  3 ; 并切換到保護模式,不過該gdt只是臨時性的,在進入kernel之后還會重新設置gdt;
  4 ; 在保護模式下將kernel從原來位置加載到指定位置,這里我們假定指定位置為0x0開始的地方。
  5 ; 移動kernel文件的方法因為文件的類型不同而不同,在linux3.0.0.12下,gcc版本4.5編譯
  6 ; 為ELF格式的二進制文件,將program segment按照編譯時指定的虛擬地址加載到相應位置。
  7 ; kernel的入口地址為KERNEL_ADDR,注意該值必須和在鏈接內核時指定的入口地址一致,
  8 ; 否則加載內核失敗;成功加載內核后便跳轉到內核執行。
  9 
 10 ; Author :
 11 ; v0.01 2011/11/22
 12 ;
 13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 14 jmp start
 15 
 16 PARAM_ADDR    equ 0xf000 ; 系統參數保存在的位置的段基址
 17 KERNEL_ADDR    equ    0x0 ; kernel入口地址,注意,此處的值一定要和編譯kernel文件時指定的入口地址相同
 18 
 19 [SECTION .code16]
 20 [BITS 16]
 21 start:
 22     mov ax, cs ; 當前cs值為:0x8000
 23     mov ds, ax
 24     mov es, ax
 25     sub ax, 0x20
 26     mov ss, ax ; ss地址為0x7fe0
 27     mov sp, 0x200 ; 堆棧大小為512B = 0.5KB
 28 
 29     ; 獲取當前光標位置
 30     mov ah, 0x03
 31     xor bh, bh
 32     int 0x10
 33 
 34     ; 打印一些信息
 35     mov ax, cs
 36     mov es, ax
 37     mov cx, MSG1_LEN
 38     mov bx, 0x0007
 39     mov bp, MSG1 ; 顯示字符串"Loading "
 40     mov ax, 0x1301
 41     int 0x10
 42 
 43     push es ; 先保存es寄存器的值
 44     mov ax, 0x0
 45     mov es, ax
 46     mov byte al, [es:0x7dfb] ; 取出保存在boot文件尾部的loader文件大小值
 47     mov byte [LOADER_LEN], al
 48     mov word ax, [es:0x7dfc]
 49     mov word [KERNEL_LEN], ax ; 取出保存在boot文件尾部的kernel文件大小值
 50     pop es
 51 
 52     ; 取得kernel的入口地址以及第一個program segment在內存中的物理地址
 53     mov bx, es
 54     xor ax, ax
 55     mov byte al, [LOADER_LEN]
 56     shl ax, 0x05
 57     add bx, ax
 58     mov es, bx ; es指向kernel文件頭部
 59     mov si, MSG3
 60     mov edi, 0x0
 61     mov cx, 0x06
 62     cld
 63     repe cmpsb
 64     cmp cx, 0x0 ; 如果kernel文件頭部的魔數確實為“kernel”,則認為是合法的kernel文件
 65     jne no_kernel
 66     mov dword eax, [es:di]
 67     cmp eax, KERNEL_ADDR
 68     jne no_kernel
 69     mov dword [KERNEL_ENTRY], eax ; 取得kernel的入口地址
 70     add di, 0x04
 71     mov word ax, [es:di]
 72     mov word [PROG_SEG_NUM], ax ; 取得kernel文件中program segment的數量
 73     add di, 0x02
 74     xor eax, eax
 75     mov ax, es
 76     shl eax, 4
 77     and edi, 0x0000ffff
 78     add eax, edi
 79     mov dword [PROG_SEG_FIRST], eax ; 保存kernel中第一個program segment在內存中的物理地址
 80 
 81     ; 下面的操作是從linux0.11中“拿”來的
 82     ; 取得當前光標位置
 83     push ds
 84     push es
 85 
 86     mov ax, PARAM_ADDR
 87     mov ds, ax
 88     mov ah, 0x03
 89     xor bh, bh
 90     int 0x10
 91 
 92     ; 獲得擴展內存大小,即1MB以后的內存大小,以KB計
 93     mov word [0], dx
 94     mov ah, 0x88
 95     int 0x15
 96     mov word [2], ax
 97 
 98     ; 顯示卡當前顯示模式
 99     mov ah, 0x0f
100     int 0x10
101     mov word [4], bx
102     mov word [6], ax
103 
104     ; 檢查顯示方式(EGA/VGA)并取參數
105     mov ah, 0x12
106     mov bl, 0x10
107     int 0x10
108     mov word [8], ax
109     mov word [10], bx
110     mov word [12], cx
111 
112     ; 取第一塊硬盤hd0的信息(復制硬盤參數表)。
113     ; 第一個硬盤參數表的首地址竟然是中斷向量0x41的向量值!
114     ; 而第二塊硬盤參數表緊接著第一個表的后面。
115     ; 中斷向量0x46的向量值也指向這第二塊硬盤的參數表首地址。
116     ; 表的長度為16字節(0x10)。
117     mov ax, 0x0000
118     mov ds, ax
119     lds si, [4 * 0x41]
120     mov ax, PARAM_ADDR
121     mov es, ax
122     mov di, 0x0080
123     mov cx, 0x10
124     rep movsb
125 
126     ; 取第二塊硬盤hd1的信息
127     mov ax, 0x0000
128     mov ds, ax
129     lds si, [4 * 0x46]
130     mov ax, PARAM_ADDR
131     mov es, ax
132     mov di, 0x0090
133     mov cx, 0x10
134     rep movsb
135 
136     ; 檢查系統是否存在第二塊硬盤,不存在則將第二個表清零。
137     mov ax, 0x1500
138     mov dl, 0x81
139     int 0x13
140     jc no_disk1
141     cmp ah, 0x03
142     je is_disk1
143 no_disk1:
144     mov ax, PARAM_ADDR
145     mov es, ax
146     mov di, 0x0090
147     mov cx, 0x10
148     mov ax, 0x00
149     rep movsb
150 
151 is_disk1:
152     pop es
153     pop ds
154     jmp setup_pm
155 
156 no_kernel:
157     ; 獲取當前光標位置
158     mov ah, 0x03
159     xor bh, bh
160     int 0x10
161 
162     ; 打印一些信息
163     mov ax, cs
164     mov es, ax
165     mov cx, MSG2_LEN
166     mov bx, 0x0007
167     mov bp, MSG2 ; 顯示字符串"[[ NO KERNEL ]]\r\nPress any key to reboot now "
168     mov ax, 0x1301
169     int 0x10
170 
171     xor ax, ax
172     int 0x16 ; 等待用戶輸入任意一個鍵盤字符
173     int 0x19 ; 系統重啟
174 
175 setup_pm:
176     ; 將保護模式代碼段基地址填入GDT1描述符中
177     xor eax, eax
178     mov ax, cs
179     shl eax, 4
180     add eax, PMCODE
181     mov word [CS_TMP + 2], ax
182     shr eax, 16
183     mov byte [CS_TMP + 4], al
184     mov byte [CS_TMP + 7], ah
185 
186     ; 將保護模式數據段基地址填入GDT1描述符中
187     xor eax, eax
188     mov ax, ds
189     shl eax, 4
190     add eax, PMDATA
191     mov word [DS_TMP + 2], ax
192     shr eax, 16
193     mov byte [DS_TMP + 4], al
194     mov byte [DS_TMP + 7], ah
195 
196     ; 填充GDTPTR結構體
197     ; 該結構體將被加載進gdtr寄存器
198     xor eax, eax
199     mov ax, ds
200     shl eax, 4
201     add eax, GDT
202     mov dword [GDTPTR + 2], eax
203 
204     lgdt [GDTPTR]
205 
206     ; 關閉中斷
207     cli
208 
209     ; 通過設置鍵盤控制器的端口值來打開A20地址線
210     call empty_8042
211     mov al, 0xd1
212     out 0x64, al
213     call empty_8042
214     mov al, 0xdf
215     out 0x60, al
216     call empty_8042
217 
218     ; 修改cr0寄存器的最后一位PE位
219     ; 注意lmsw指令僅僅對cr0寄存器的最后四位有影響
220     mov eax, cr0
221     or eax, 0x01
222     lmsw ax
223 
224     ; 真正跳轉到保護模式!!!!!!
225     jmp dword 0x08:0x00
226 
227 empty_8042:
228     nop
229     nop
230     in al, 0x64
231     test al, 0x02
232     jnz empty_8042
233     ret
234 
235 [section .pmcode]
236 align 32
237 [bits 32]
238 PMCODE:
239     mov ax, 0x10
240     mov ds, ax
241     xor ecx, ecx
242     mov word cx, [pm_PROG_SEG_NUM] ; 取得kernel文件中program segment的段數
243     mov dword esi, [pm_PROG_SEG_FIRST] ; 取得kernel文件中的第一個program segment的地址
244     mov ax, 0x20
245     mov ds, ax
246     mov es, ax
247 move_kernel:
248     push ecx
249     mov ecx, [esi] ; 取得program segment在文件中的大小
250     add esi, 4
251     mov edi, [esi] ; 取得段在內存中的地址
252     add esi, 4
253     cld
254     rep movsb
255     pop ecx
256     loop move_kernel
257 
258     mov ax, 0x20
259     mov ds, ax
260     mov es, ax
261     mov ss, ax
262     mov fs, ax
263     mov gs, ax
264     jmp 0x18:KERNEL_ADDR
265 
266 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
267 ; GDT描述符中由低到高的含義如下:
268 ;  BYTE7  || BYTE6 BYTE5 || BYTE4 BYTE3 BYTE2 || BYTE1 BYTE0 ||
269 ; 段基地址||      屬性   ||       段基址      ||    段界限   ||
270 ; (31-24||             ||      (23-0)       ||    (15-0)   ||
271 ;
272 ; 屬性含義如下:
273 7 || 6 || 5 || 4 || 3   2   1   0 || 7 || 6 || 5 || 4   3   2  1   0 ||
274 ; G ||D/B|| 0 ||AVL|| 段界限(19-16|| P ||DPL|| S ||       TYPE       ||
275 ;
276 ; G位:段界限的粒度,0為字節,1為4KB
277 ; D/B;在可執行代碼段中,這一位叫做D位:
278 ;        D=1時指令使用32位地址及32位或8位操作數;D=0時使用16位地址及16位或8位操作數
279 ;      在數據段描述符中,這一位叫做B位:
280 ;        B=1時段上部界限為4GB;B=0時段上部界限為64KB
281 ;      在堆棧段描述符中,這一位叫做B位:
282 ;        B=1時隱式的堆棧訪問指令(比如push、pop、call等)使用32位堆棧指針寄存器esp
283 ;        B=0時隱式的堆棧訪問指令使用16位堆棧指針寄存器sp
284 ; AVL: 保留
285 ; P位: 1代表段在內存中存在;0代表段在內存中不存在
286 ; DPL:描述符特權級
287 ; S位:1代表是數據段或者代碼段描述符;0代表是系統段或者門描述符
288 ;TYPE:說明描述符類型
289 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
290 
291 [section .pmdata]
292 align 32
293 [bits 32]
294 PMDATA:
295         ; 第一個描述符空,不使用
296 GDT:    db 0x00,    0x00
297         db 0x00,    0x00,    0x00
298         db 0x00,    0x00
299         db 0x00
300 
301         ; 第二個描述符為保護模式代碼所在的段
302         ; 段基地址在切換到保護模式前填入;
303         ; 界限為0xfffff,段界限粒度為4KB,因此段長為4GB;
304         ; 是可執行可讀的32位代碼段
305 CS_TMP:    db 0xff,    0xff
306         db 0x00,    0x00,    0x00
307         db 0x9a,    0xcf
308         db 0x00
309 
310         ; 第三個描述符為切換到保護模式用到的數據段
311         ; 段基地址為PMDATA,在切換到保護模式前填入;
312         ; 界限為0xfffff,段界限粒度為4KB,因此段長為4GB;
313         ; 是可讀可寫32位數據段
314 DS_TMP:    db 0xff,    0xff
315         db 0x00,    0x00,    0x00
316         db 0x92,    0xcf
317         db 0x00
318 
319         ; 第四個描述符的段基地址為0;
320         ; 界限為0xfffff,段界限粒度為4KB;
321         ; 是可執行可讀的32位代碼段
322 CODE:    db 0xff,    0xff
323         db 0x00,    0x00,    0x00
324         db 0x9a,    0xcf
325         db 0x00
326 
327         ; 第五個描述符的段基地址為0;
328         ; 界限為0xfffff,段界限粒度為4KB;
329         ; 是可讀可寫32位數據段
330 DATA:    db 0xff,    0xff
331         db 0x00,    0x00,    0x00
332         db 0x92,    0xcf
333         db 0x00
334 
335 GDT_LEN                equ $ - GDT
336 GDTPTR                dw GDT_LEN - 1
337                     dd 0
338 
339 ; 在實模式下直接使用LOADER_LEN等標號就能取出內存中的內容
340 ; 在保護模式下想要取LOADER_LEN等內存中的內容需要使用基于段基地址的偏移
341 pm_LOADER_LEN        equ $ - PMDATA
342 LOADER_LEN:            db 0 ; 記錄loader文件的大小
343 
344 pm_KERNEL_LEN        equ $ - PMDATA
345 KERNEL_LEN:            dw 0 ; 記錄kernel文件的大小,注意,這里指的是從System.Image解壓出來前的大小
346 
347 pm_KERNEL_ENTRY        equ $ - PMDATA
348 KERNEL_ENTRY:        dd 0 ; 記錄kernel的入口虛擬地址
349 
350 pm_PROG_SEG_FIRST    equ $ - PMDATA
351 PROG_SEG_FIRST        dd 0 ; 記錄kerne文件中第一個program segment在內存中的物理地址
352 
353 pm_PROG_SEG_NUM        equ $ - PMDATA
354 PROG_SEG_NUM        dw 0 ; 記錄kerne文件中program segment的數量
355 
356 ; 以下為在實模式下需要打印的字符串
357 MSG1:                db 1310"Loading "1310
358 MSG1_LEN            equ $ - MSG1
359 
360 MSG2:                db 1310"[[ NO KERNEL ]]"1310"Press any key to reboot now "1310
361 MSG2_LEN            equ $ - MSG2
362 
363 MSG3:                db "kernel"
364 MSG3_LEN            equ $ - MSG3
365 

     思路比較清晰,首先保存系統參數,這個步驟是從linux中拿過來的,會在以后分頁機制以及tty中用到;其次是將內核移動到內存地址0x0的位置,這部分需要參照
http://m.shnenglu.com/myjfm/archive/2011/11/20/160556.htmlhttp://m.shnenglu.com/myjfm/archive/2011/11/20/160558.html兩部分,這兩部分是kernel的組織方式,將ELF格式的kernel分program segment移動到指定位置;最后是切換進入保護模式,這里需要加載gdt,loader準備了5個全局段描述符,其中兩個是專門為剛剛切換到保護模式后運行所準備的代碼段和數據段描述符。兩外兩個是從絕對物理地址0x0開始,大小為4G的代碼段和數據段描述符,不過等到進入kernel還需要重新設置段描述符,因此這只是權易之計。
posted on 2011-11-22 20:08 myjfm 閱讀(752) 評論(0)  編輯 收藏 引用 所屬分類: 操作系統
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品偷拍| 亚洲欧美日韩国产精品| 亚洲女优在线| 亚洲欧美日韩视频一区| 午夜视频一区| 久久久久久久久一区二区| 久久精品国产久精国产爱| 久久久夜夜夜| 亚洲人午夜精品| 最新日韩欧美| 亚洲无人区一区| 久久福利资源站| 久久综合九色综合欧美狠狠| 久久综合精品国产一区二区三区| 欧美国产日韩一区二区在线观看 | 久久视频国产精品免费视频在线| 久久在线免费| aⅴ色国产欧美| 久久久久九九九| 欧美日韩直播| 亚洲高清视频中文字幕| 亚洲天堂网在线观看| 久久精品视频免费观看| 亚洲欧洲精品一区二区三区波多野1战4 | **欧美日韩vr在线| 亚洲视频一二区| 美乳少妇欧美精品| 国产精品99久久久久久白浆小说 | 一区二区三区|亚洲午夜| 欧美在线精品一区| 亚洲精品一区二区三区不| 久久国产精品毛片| 国产精品国产一区二区| 亚洲日本va午夜在线电影 | 99精品国产福利在线观看免费| 久久国产精品亚洲77777| 欧美视频亚洲视频| 日韩视频不卡| 欧美大片网址| 久久久久久精| 国产日韩亚洲| 性欧美长视频| 亚洲一区二区三区免费观看| 欧美日韩国产首页| 欧美在线观看一区| 最近看过的日韩成人| 午夜精品一区二区三区在线播放| 欧美福利视频在线观看| 亚洲欧美日韩人成在线播放| 欧美日韩国产一区| 99视频精品全部免费在线| 欧美激情中文字幕一区二区| 久久噜噜亚洲综合| 在线电影国产精品| 日韩视频精品在线| 欧美专区亚洲专区| 免费观看一区| 亚洲高清久久久| 麻豆成人在线观看| 久久久久久久91| 伊人久久噜噜噜躁狠狠躁| 久久亚洲欧洲| 久久精品国产清高在天天线| 国产午夜一区二区三区| 久久精品国产999大香线蕉| 亚洲综合国产精品| 国产视频久久网| 久久人人97超碰精品888| 久久久噜噜噜久久| 亚洲国产精品久久久久婷婷884| 免费国产一区二区| 理论片一区二区在线| 亚洲欧洲精品一区| 日韩视频永久免费| 国产区精品视频| 久久免费国产精品1| 久久亚洲一区二区三区四区| 亚洲国产综合视频在线观看| 亚洲国产一区二区三区青草影视 | 欧美精品日韩www.p站| 一本一本a久久| 亚洲午夜精品网| 韩国一区二区三区在线观看| 欧美激情亚洲自拍| 国产精品yjizz| 久久久中精品2020中文| 免费日韩成人| 亚洲欧美日韩视频二区| 久久爱www久久做| 亚洲精品乱码久久久久久日本蜜臀| 日韩视频在线永久播放| 国产有码一区二区| 亚洲日韩视频| 国内精品伊人久久久久av一坑| 欧美激情精品久久久久久| 国产精品无人区| 亚洲国产成人精品视频| 国产精品一区二区男女羞羞无遮挡 | 美日韩精品免费观看视频| 一区二区三区视频在线播放| 亚洲欧美综合| 日韩午夜黄色| 久久激情网站| 亚洲欧美乱综合| 欧美成人资源网| 久久精品在线| 欧美三区在线| 亚洲高清在线播放| 国产一区二区三区久久悠悠色av | 亚洲高清免费| 国产一区二区精品久久99| 亚洲激情在线播放| 精品福利电影| 欧美亚洲免费高清在线观看| 亚洲午夜电影| 欧美黑人国产人伦爽爽爽| 久久婷婷丁香| 国产女主播一区二区| 亚洲欧洲一二三| 亚洲国产天堂久久国产91| 久久精品国产999大香线蕉| 亚洲女性裸体视频| 欧美天堂亚洲电影院在线播放| 亚洲福利精品| 亚洲人成人一区二区三区| 久久综合狠狠综合久久激情| 久久天堂国产精品| 国内精品福利| 欧美中在线观看| 久久久精品久久久久| 国产拍揄自揄精品视频麻豆| 亚洲欧美日韩国产一区| 欧美一区三区二区在线观看| 国产精品美女一区二区在线观看| 亚洲伦伦在线| 亚洲婷婷国产精品电影人久久| 欧美日韩ab| 妖精成人www高清在线观看| 在线综合亚洲欧美在线视频| 欧美日韩亚洲综合一区| 这里只有精品丝袜| 欧美在线亚洲在线| 国产亚洲精品综合一区91| 久久久www成人免费精品| 免费日韩成人| 99re66热这里只有精品3直播| 欧美日韩不卡视频| 亚洲视频第一页| 浪潮色综合久久天堂| 亚洲精品久久久久久久久| 欧美日韩国产a| 亚洲一区三区视频在线观看 | 日韩亚洲精品电影| 欧美精品一区二区三区在线看午夜| 亚洲精品国产品国语在线app| 一区二区三区不卡视频在线观看| 欧美色大人视频| 久久频这里精品99香蕉| 久久狠狠久久综合桃花| 亚洲婷婷免费| 欧美婷婷在线| 午夜国产一区| 欧美成人精品不卡视频在线观看| 亚洲精品欧美精品| 欧美午夜精品久久久久久久| 欧美一区二区三区在线观看| 欧美ab在线视频| 亚洲视频二区| 国精产品99永久一区一区| 嫩草成人www欧美| 日韩一级黄色大片| 久久手机精品视频| 日韩小视频在线观看| 国产精品视频免费观看www| 久久综合狠狠综合久久激情| 亚洲青涩在线| 久久久久久久一区二区| 日韩亚洲欧美成人一区| 国产美女一区| 欧美日韩一区二区三区四区五区| 性久久久久久久久久久久| 亚洲激情成人| 久久精品视频网| 亚洲午夜精品一区二区三区他趣| 一区二区亚洲| 国产精品一区二区三区四区五区| 免费日韩一区二区| 欧美在线在线| 亚洲在线1234| aⅴ色国产欧美| 亚洲黄色天堂| 美国成人直播| 久久av一区二区三区亚洲| 日韩视频在线一区二区| 黄色成人在线网站| 国产欧美欧美| 国产精品天美传媒入口| 欧美激情亚洲国产| 久久婷婷久久一区二区三区| 久久爱另类一区二区小说|