国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

自己動(dòng)手寫操作系統(tǒng)(三)

2024-07-21 02:37:15
字體:
供稿:網(wǎng)友

  在上兩期中(自己動(dòng)手寫操作系統(tǒng)1,2),我向大家講述了如何使用linux提供的開發(fā)工具在軟盤的啟動(dòng)扇區(qū)寫一些代碼,以及如何調(diào)用BIOS的問題。現(xiàn)在,這個(gè)操作系統(tǒng)已經(jīng)越來越接近當(dāng)年Linus Torvalds的那個(gè)具有“歷史意義”的Linux內(nèi)核了。 因此,要馬上把這個(gè)系統(tǒng)切換到保護(hù)模式之下。
  
  什么是保護(hù)模式
  
  自從1969年推出第一個(gè)微處理器以來,Intel處理器就在不斷地更新?lián)Q代,從8086、8088、80286,到80386、80486、奔騰、奔騰Ⅱ、奔騰4等,其體系結(jié)構(gòu)也在不斷變化。80386以后,提供了一些新的功能,彌補(bǔ)了8086的一些缺陷。這其中包括內(nèi)存保護(hù)、多任務(wù)及使用640KB以上的內(nèi)存等,并仍然保持和8086家族的兼容性。也就是說80386仍然具備了8086和80286的所有功能,但是在功能上有了很大的增強(qiáng)。早期的處理器是工作在實(shí)模式之下的,80286以后引入了保護(hù)模式,而在80386以后保護(hù)模式又進(jìn)行了很大的改進(jìn)。在80386中,保護(hù)模式為程序員提供了更好的保護(hù),提供了更多的內(nèi)存。事實(shí)上,保護(hù)模式的目的不是為了保護(hù)程序,而是要保護(hù)程序以外的所有程序(包括操作系統(tǒng))。
  
  簡(jiǎn)言之,保護(hù)模式是處理器的一種最自然的模式。在這種模式下,處理器的所有指令及體系結(jié)構(gòu)的所有特色都是可用的,并且能夠達(dá)到最高的性能。
  
  保護(hù)模式和實(shí)模式
  
  從表面上看,保護(hù)模式和實(shí)模式并沒有太大的區(qū)別,二者都使用了內(nèi)存段、中斷和設(shè)備驅(qū)動(dòng)來處理硬件,但二者有很多不同之處。我們知道,在實(shí)模式中內(nèi)存被劃分成段,每個(gè)段的大小為64KB,而這樣的段地址可以用16位來表示。內(nèi)存段的處理是通過和段寄存器相關(guān)聯(lián)的內(nèi)部機(jī)制來處理的,這些段寄存器(CS、DS、SS和ES)的內(nèi)容形成了物理地址的一部分。具體來說,最終的物理地址是由16位的段地址和16位的段內(nèi)偏移地址組成的。用公式表示為:
  
  物理地址=左移4位的段地址+偏移地址。
  
  在保護(hù)模式下,段是通過一系列被稱之為“描述符表”的表所定義的。段寄存器存儲(chǔ)的是指向這些表的指針。用于定義內(nèi)存段的表有兩種:全局描述符表(GDT)和局部描述符表(LDT)。GDT是一個(gè)段描述符數(shù)組,其中包含所有應(yīng)用程序都可以使用的基本描述符。在實(shí)模式中,段長(zhǎng)是固定的(為64KB),而在保護(hù)模式中,段長(zhǎng)是可變的,其最大可達(dá)4GB。LDT也是段描述符的一個(gè)數(shù)組。與GDT不同,LDT是一個(gè)段,其中存放的是局部的、不需要全局共享的段描述符。每一個(gè)操作系統(tǒng)都必須定義一個(gè)GDT,而每一個(gè)正在運(yùn)行的任務(wù)都會(huì)有一個(gè)相應(yīng)的LDT。每一個(gè)描述符的長(zhǎng)度是8個(gè)字節(jié),格式如圖3所示。當(dāng)段寄存器被加載的時(shí)候,段基地址就會(huì)從相應(yīng)的表入口獲得。描述符的內(nèi)容會(huì)被存儲(chǔ)在一個(gè)程序員不可見的影像寄存器(shadow register)之中,以便下一次同一個(gè)段可以使用該信息而不用每次都到表中提取。物理地址由16位或者32位的偏移加上影像寄存器中的基址組成。實(shí)模式和保護(hù)模式的不同可以從圖1和圖2中很清楚地看出來。
   自己動(dòng)手寫操作系統(tǒng)(三)(圖一)
  圖1 實(shí)模式的尋址
   自己動(dòng)手寫操作系統(tǒng)(三)(圖二)
  圖2 保護(hù)模式下的尋址
  自己動(dòng)手寫操作系統(tǒng)(三)(圖三)
  圖3 段描述俯的格式
  
  此外,還有一個(gè)中斷描述符表(IDT)。這些中斷描述符會(huì)告訴處理器到那里可以找到中斷處理程序。和實(shí)模式一樣,每一個(gè)中斷都有一個(gè)入口,但是這些入口的格式卻完全不同。因?yàn)樵谇袚Q到保護(hù)模式的過程中沒有使用到IDT,所以在此就不多做介紹了。
  
  進(jìn)入保護(hù)模式
  
  80386有4個(gè)32位控制寄存器,名字分別為CR0、CR1、CR2和CR3。CR1是保留在未來處理器中使用的,在80386中沒有定義。CR0包含系統(tǒng)的控制標(biāo)志,用于控制處理器的操作模式和狀態(tài)。CR2和CR3是用于控制分頁機(jī)制的。在此,我們關(guān)注的是CR0寄存器的PE位控制,它負(fù)責(zé)實(shí)模式和保護(hù)模式之間的切換。當(dāng)PE=1時(shí),說明處理器運(yùn)行于保護(hù)模式之下,其采用的段機(jī)制和前面所述的相應(yīng)內(nèi)容對(duì)應(yīng)。假如PE=0,那么處理器就工作在實(shí)模式之下。
  
  切換到保護(hù)模式,實(shí)際就是把PE位置為1。為了把系統(tǒng)切換到保護(hù)模式,還要做一些其它的事情。程序必須要對(duì)系統(tǒng)的段寄存器和控制寄存器進(jìn)行初始化。把PE位置1后,還要執(zhí)行跳轉(zhuǎn)指令。過程簡(jiǎn)述如下:
  
  1.創(chuàng)建GDT表;
  
  2.通過置PE位為1進(jìn)入保護(hù)模式;
  
  3.執(zhí)行跳轉(zhuǎn)以清除在實(shí)模式下讀取的任何指令。
  
  下面使用代碼來實(shí)現(xiàn)這個(gè)切換過程。
  
  需要的東西
  
  ◆ 一張空白軟盤
  
  ◆ NASM編譯器
  
  下面是整個(gè)程序的源代碼:
  
  org 0x07c00; 起始地址是0000:7c00
  jmp short begin_boot  ; 跳過其它的數(shù)據(jù),跳轉(zhuǎn)到引導(dǎo)程序的開始處
  bootmesg db "Our OS boot sector loading ......"
  pm_mesg db "Switching to PRotected mode ...."
  dw 512 ; 每一扇區(qū)的字節(jié)數(shù)
  db 1 ; 每一簇的扇區(qū)數(shù)
  dw 1 ; 保留的扇區(qū)號(hào)
  db 2   
  dw 0x00e0   
  dw 0x0b40   
  db 0x0f0   
  dw 9   
  dw 18   
  dw 2 ; 讀寫扇區(qū)號(hào)
  dw 0 ; 隱藏扇區(qū)號(hào)
  print_mesg :
  mov ah,0x13 ; 使用中斷10h的功能13,在屏幕上寫一個(gè)字符串
  mov al,0x00 ; 決定調(diào)用函數(shù)后光標(biāo)所處的位置
  mov bx,0x0007  ; 設(shè)置顯示屬性
  mov cx,0x20 ; 在此字符串長(zhǎng)度為32
  mov dx,0x0000  ; 光標(biāo)的起始行和列
  int 0x10 ; 調(diào)用BIOS的中斷10h
  ret ; 返回調(diào)用程序
  get_key :
  mov ah,0x00  
  int 0x16 ; Get_key使用中斷16h的功能0,讀取下一個(gè)字符
  ret
  clrscr :
  mov ax,0x0600 ; 使用中斷10h的功能6,實(shí)現(xiàn)卷屏,假如al=0則清屏
  mov cx,0x0000 ; 清屏
  mov dx,0x174f ; 卷屏至23,79
  mov bh,0 ; 使用顏色0來填充
  int 0x10 ; 調(diào)用10h中斷
  ret
  begin_boot :
  call clrscr  ; 先清屏
  mov bp,bootmesg ; 提供串地址
  call print_mesg ; 輸出信息
  call get_key  ; 等待用戶按下任一鍵
  bits 16
  call clrscr ; 清屏
  mov ax,0xb800 ; 使gs指向顯示內(nèi)存
  mov gs,ax ; 在實(shí)模式下顯示一個(gè)棕色的A
  mov Word [gs:0],0x641 ; 顯示
  call get_key ; 調(diào)用Get_key等待用戶按下任一鍵
  mov bp,pm_mesg ; 設(shè)置串指針
  call print_mesg ; 調(diào)用print_mesg子程序
  call get_key ; 等待按鍵
  call clrscr ; 清屏
  cli ; 關(guān)中斷
  lgdt[gdtr] ; 加載GDT
  mov eax,cr0   
  or al,0x01 ; 設(shè)置保護(hù)模式位
  mov cr0,eax ; 將更改后的字送至控制寄存器中
  jmp codesel:go_pm
  bits 32
  go_pm :
  mov ax,datasel 
  mov ds,ax ; 初始化ds和es,使其指向數(shù)據(jù)段
  mov es,ax
  mov ax,videosel ; 初始化gs,使其指向顯示內(nèi)存
  mov gs,ax
  mov word [gs:0],0x741 ; 在保護(hù)模式下顯示一個(gè)白色的字符A
  spin : jmp spin ; 循環(huán)
  bits 16
  gdtr :
  dw gdt_end-gdt-1 ; gdt的長(zhǎng)度
  dd gdt ; gdt的物理地址
  gdt
  nullsel equ $-gdt ; $指向當(dāng)前位置,所以nullsel = 0h
  gdt0 ; 空描述符
  dd 0    
  dd 0 ; 所有的段描述符都是64位的
  codesel equ $-gdt ; 這是8h也就是gdt的第二個(gè)描述符
  code_gdt    
  dw 0x0ffff ; 段描述符的界限是4Gb
  dw 0x0000    
  db 0x00      
  db 0x09a  
  db 0x0cf  
  db 0x00  
  datasel equ $-gdt  
  data_gdt    
  dw 0x0ffff    
  dw 0x0000    
  db 0x00      
  db 0x092
  db 0x0cf
  db 0x00
  videosel equ $-gdt   
  dw 3999    
  dw 0x8000 ; 基址是0xb8000
  db 0x0b
  db 0x92    
  db 0x00    
  db 0x00
  gdt_end
  times 510-($-$$) db 0 
  dw 0x0aa55
  
  把上面的代碼存在一個(gè)名為abc.asm的文件之中,使用命令nasm abc.asm,將得出一個(gè)名為abc的文件。
然后插入軟盤,輸入命令:dd if=abc of=/dev/fd0。該命令將把文件abc寫入到軟盤的第一扇區(qū)之中。然后重新啟動(dòng)系統(tǒng),就會(huì)看到如下的信息:
  
  *Our os booting................
  * A (棕色)
  * Switching to protected mode....
  * A (白色)
  
  對(duì)代碼的解釋
  
  上面給出了所有的代碼,下面我對(duì)上述代碼做一些解釋。
  
  ◆ 使用的函數(shù)
  
  下面是代碼中一些函數(shù)的說明:
  
  print_mesg 該子程序使用了BIOS中斷10h的功能13h,即向屏幕寫一字符串。屬性控制是通過向一些寄存器中送入不同的值來實(shí)現(xiàn)的。中斷10h是用于各種字符串操作,我們把子功能號(hào)13h送到ah中,用于指明要打印一個(gè)字符串。al寄存器中的0說明了光標(biāo)返回的起始位置,0表示調(diào)用函數(shù)后光標(biāo)返回到下一行的行首。假如al為1則表示光標(biāo)位于最后一個(gè)字符處。
  
  顯存被分成了幾頁,在同一時(shí)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 新邵县| 元江| 沾化县| 肃宁县| 安岳县| 宁乡县| 武义县| 株洲县| 甘洛县| 荔波县| 花垣县| 建德市| 全南县| 阜城县| 青河县| 龙陵县| 锡林浩特市| 仁怀市| 阳泉市| 神木县| 苏尼特右旗| 方城县| 呼伦贝尔市| 连平县| 利川市| 玛多县| 毕节市| 长武县| 体育| 赣州市| 亳州市| 阿拉尔市| 满城县| 台南县| 方正县| 永靖县| 泸州市| 乌兰浩特市| 缙云县| 博湖县| 资兴市|