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

隨筆-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>
            亚洲制服欧美中文字幕中文字幕| 国产九九精品| 99在线热播精品免费99热| 欧美成人xxx| 欧美激情第10页| 亚洲老板91色精品久久| 亚洲黄色尤物视频| 免费一级欧美片在线观看| 久久久91精品国产| 麻豆精品一区二区综合av | 亚洲风情亚aⅴ在线发布| 鲁鲁狠狠狠7777一区二区| 久久综合网络一区二区| 欧美国产精品v| 亚洲作爱视频| 久久精品日产第一区二区三区 | 国产人成一区二区三区影院| 久久午夜视频| 久久五月婷婷丁香社区| 欧美成人免费全部| 一区二区免费在线视频| 欧美精品一区二区蜜臀亚洲| 久久夜色精品一区| 欧美三日本三级少妇三99| 国产一区二区三区在线观看免费| 狠狠久久婷婷| 一本色道久久88亚洲综合88| 欧美一区二区三区的| 欧美~级网站不卡| 一区二区三区日韩欧美| 久久亚洲综合网| 欧美午夜a级限制福利片| 国产一区二区精品久久99| 一区二区精品| 免费观看不卡av| 亚洲欧美另类久久久精品2019| 国产主播精品| 乱人伦精品视频在线观看| 亚洲国产高潮在线观看| 亚洲女同精品视频| 欧美日韩在线免费观看| 亚洲国产成人高清精品| 欧美一区永久视频免费观看| 亚洲激情综合| 另类国产ts人妖高潮视频| 国产日韩欧美亚洲一区| 一区二区欧美日韩视频| 欧美电影在线免费观看网站| 欧美一级一区| 国产精品外国| 亚洲在线观看| 一本久道久久综合婷婷鲸鱼| 欧美大尺度在线| 免费不卡中文字幕视频| 99精品国产在热久久| 欧美激情一区二区三区高清视频 | 欧美日韩精品免费观看视频| 亚洲国产精品一区在线观看不卡| 久久成人18免费网站| 一区二区三区欧美| 欧美日韩在线精品| 亚洲午夜女主播在线直播| 亚洲精品中文在线| 欧美日韩一区二区三区在线观看免| 亚洲国产小视频| 亚洲国产成人在线| 欧美成va人片在线观看| 亚洲黄色在线观看| 亚洲福利一区| 欧美日韩亚洲高清| 亚洲欧美日韩一区二区三区在线| 亚洲天堂av电影| 国产精品中文字幕欧美| 亚洲欧洲一区二区三区在线观看| 国产免费成人在线视频| 欧美一区二区成人| 午夜在线视频一区二区区别| 老**午夜毛片一区二区三区| 狠狠综合久久| 欧美激情视频一区二区三区不卡| 欧美成在线观看| 亚洲在线日韩| 久久久免费精品视频| 亚洲国产精品尤物yw在线观看| 女生裸体视频一区二区三区| 男女激情视频一区| 亚洲天堂男人| 欧美在线视频免费| 最近中文字幕mv在线一区二区三区四区| 欧美肥婆在线| 亚洲国产第一| 99riav久久精品riav| 国产精品福利在线观看网址| 欧美自拍丝袜亚洲| 欧美成人精品福利| 亚洲欧美成aⅴ人在线观看| 亚洲欧美中文日韩v在线观看| 国内精品久久久久影院优| 亚洲国产高清一区| 国产精品综合av一区二区国产馆| 久久亚洲精品一区| 欧美日韩一区二区精品| 久久影院亚洲| 国产精品毛片va一区二区三区| 葵司免费一区二区三区四区五区| 欧美日本亚洲| 欧美大片免费久久精品三p| 国产精品久久久久久久久久免费 | 99精品视频一区二区三区| 这里是久久伊人| 在线看一区二区| 亚洲欧美日韩直播| av成人黄色| 美女国产一区| 久久久国产精品一区二区中文 | **欧美日韩vr在线| 一区二区欧美日韩| 亚洲国产美国国产综合一区二区| 亚洲女ⅴideoshd黑人| 日韩一区二区免费高清| 99这里有精品| 亚洲一区二区三区四区中文| 亚洲精品一二三| 久久久夜夜夜| 亚洲欧美另类中文字幕| 一区二区三区视频在线播放| 久久久爽爽爽美女图片| 性欧美长视频| 欧美视频手机在线| 亚洲美女一区| 中国亚洲黄色| 欧美视频一区| 亚洲精品视频在线播放| 亚洲欧洲日韩综合二区| 久久综合久久久久88| 美女主播一区| 亚洲成人在线网| 免费一级欧美片在线播放| 欧美国产精品v| 亚洲精品乱码久久久久久黑人| 六月丁香综合| 91久久夜色精品国产九色| 最新精品在线| 欧美伦理在线观看| 亚洲网在线观看| 欧美午夜在线| 亚洲欧美另类国产| 久久五月婷婷丁香社区| 影音先锋中文字幕一区二区| 久久国产欧美| 欧美成人69| 日韩系列在线| 欧美午夜视频在线| 欧美在线视频日韩| 欧美第十八页| 美女亚洲精品| 久久国产精品黑丝| 欧美华人在线视频| 一区二区日本视频| 国产精品永久在线| 久久综合九色综合网站| 亚洲国产一区视频| 亚洲欧美另类在线| 亚洲国产成人不卡| 国产精品视频导航| 亚洲私人影吧| 亚洲免费在线视频一区 二区| 久久久在线视频| 日韩午夜高潮| 国产日韩综合一区二区性色av| 久久嫩草精品久久久精品| 亚洲精品欧美日韩专区| 欧美一区二区久久久| 亚洲国产美女| 国产欧美一区二区三区视频| 免费在线成人av| 亚洲欧美国产日韩中文字幕| 亚洲国产导航| 久久综合九色| 亚洲尤物影院| 亚洲精品久久久久久久久久久久 | 男女av一区三区二区色多| 一本色道久久综合狠狠躁篇怎么玩| 久久国内精品自在自线400部| 最新成人在线| 狠狠久久亚洲欧美专区| 国产精品国产三级欧美二区| 久久久av水蜜桃| av成人黄色| 亚洲人成亚洲人成在线观看| 欧美激情精品久久久久| 香蕉久久国产| 一本色道久久综合亚洲精品不卡 | 久久亚裔精品欧美| 一区二区三区高清在线| 亚洲激精日韩激精欧美精品| 国产亚洲欧美一区二区| 国产精品久久波多野结衣| 欧美搞黄网站| 六月天综合网|