<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      前言

      今天本來的任務(wù)看書和把之前寫的FragileOS <https://github.com/dejavudwh/FragileOS>
      整理一下,但是到現(xiàn)在還在摸魚,書也只看一點。后來整理了一下寫這個系列的思路,原本的目的是對操作系統(tǒng)原理性的學(xué)習(xí)和對之前寫的一個玩具型操作系統(tǒng)的回顧,就是想對操作系統(tǒng)的知識的輪廓能有一個了解,現(xiàn)在想來想減少對之前寫的系統(tǒng)的回顧,畢竟也只有2000多行,但是還是要有對整個思路的展現(xiàn)。然后增加對Linux
      0.12源碼的一些學(xué)習(xí)。所以離標題可能比較遠了一點,但是就這樣吧

      什么是操作系統(tǒng)




      原本這一節(jié)是寫計算機系統(tǒng)和操作系統(tǒng)概述的,但是寫到一半覺得太水就刪了。就總結(jié)幾句,后面用到什么就補什么。計算機系統(tǒng)的概述應(yīng)該屬于計算機組成原理的內(nèi)容,這倆部分也是《操作系統(tǒng):精髓和設(shè)計原理》的第一二章。但是覺得如果對于想學(xué)習(xí)操作系統(tǒng)內(nèi)部的代碼的話,換成匯編的內(nèi)容會更好。

      進入正題,操作系統(tǒng)是什么

      對于計算機來說最根本的運行方式,就是取指執(zhí)行


      對于在屏幕上輸出Hello,World!的過程,首先CPU拿到內(nèi)存中的指令,這些指令是通知CPU把存在某個內(nèi)存中的'H''E''L'等移動到顯存位置,這樣在屏幕上就可以看到這些字符了。這就是計算機最原始的運行方式

      而操作系統(tǒng)就是對硬件層面的抽象,讓我們不用在直面硬件,如果想要再次在屏幕輸出字符,只要直接調(diào)用操作系統(tǒng)的write(windows下的好像是這個名
      ),C語言中的printf下就是一個系統(tǒng)調(diào)用

      當(dāng)然操作系統(tǒng)絕對是比想象中的龐大的多,操作系統(tǒng)還對內(nèi)存、終端、磁盤、網(wǎng)絡(luò)和文件等等進行管理,光windows
      2000應(yīng)該就有3000多萬行的代碼了。當(dāng)然有簡陋的內(nèi)存、進程管理和文件系統(tǒng)的玩具型內(nèi)核,只要幾千行代碼就可以完成了。

      操作系統(tǒng)的啟動

      對于X86架構(gòu)的計算機,開機時一共做這幾件事

      *
      開機時的CS = 0xFFFF, IP = 0x0000

      這時候的CPU處理實模式,也就是尋址的方式是CS:IP (實模式和保護模式屬于CPU的工作模式,其中比較大的區(qū)別就是尋址的方式)

      *
      尋址0xFFFF0

      *
      檢查硬件設(shè)備,像鍵盤顯示器之類的

      *
      將磁盤0磁道0扇區(qū)讀入0x7c00處

      會從這里讀入512字節(jié),也就是傳說中的引導(dǎo)程序,這里放著計算機執(zhí)行的第一段代碼

      *
      設(shè)置cs = 0x7c00 ip = 0x0000

      FragileOS/boot

      這個是我之前寫的FragileOS <https://github.com/dejavudwh/FragileOS>的boot,采用的是Intel匯編格式

      主要的邏輯就是:

      * 先加載到0x7c00位置
      * 進行初始化操作
      * 調(diào)用CPU提供的中斷來讀取數(shù)據(jù)
      * 讀取完畢后直接跳到內(nèi)核的起始位置,也就是引導(dǎo)結(jié)束了
      (部分代碼)
      org 0x7c00; ;加載到內(nèi)存0x7c00處 LoadAddr EQU 08000h ;內(nèi)核的內(nèi)存地址 BufferAddr EQU 7E0h
      ;讀取扇區(qū)的時候進行的緩存 BaseOfStack EQU 07c00h entry: mov ax, 0 ;進行寄存器的初始化操作 mov ss, ax
      mov ds, ax mov ax, BufferAddr mov es, ax ;ES:BX 數(shù)據(jù)存儲緩沖區(qū),指示扇區(qū)加載后放置的地址 mov ax, 0
      mov ss, ax mov sp, BaseOfStack mov di, ax mov si, ax mov BX, 0 ;ES:BX 數(shù)據(jù)存儲緩沖區(qū)
      mov CH, 1 ;CH 用來存儲柱面號 mov DH, 0 ;DH 用來存儲磁頭號 mov CL, 0 ;CL 用來存儲扇區(qū)號 read_floppy:
      ;每次都把扇區(qū)寫入緩存地址07E00處 cmp byte [load_count], 0
      ;比較load_count地址處的值,如果=0就跳轉(zhuǎn)到begin_load je begin_load mov bx, 0 inc CL mov AH,
      0x02 ;AH = 02 表示要做的是讀盤操作 mov AL, 1 ;AL 表示要練習(xí)讀取幾個扇區(qū) mov DL, 0
      ;驅(qū)動器編號,一般我們只有一個軟盤驅(qū)動器,所以寫死 int 0x13 ;調(diào)用BIOS中斷實現(xiàn)磁盤讀取功能 jc fin
      Linux 0.12/boot

      Linux 0.12的boot自然比上面的復(fù)雜的多,Linux采用的boot的匯編是as86格式的,其余的匯編采用的都是AT&T

      Linux 0.12下的boot一共有三個文件:

      * bootsect
      * head
      * setup
      (代碼太長不全部貼了,有需要的可以私信我)

      bootsect

      bootsect的主要作用就是把自己移動到0x90000處執(zhí)行,然后再加載setup模塊 (也就是setup.s)
      到bootsect的后面,再把system模塊加載到0x10000處,這個也就是內(nèi)核的主要部分

      bootsect的開頭是一些常量的定義
      SETUPLEN = 4 ! nr of setup-sectors BOOTSEG = 0x07c0 ! original address of
      boot-sector INITSEG = 0x9000 ! we move boot here - out of the way SETUPSEG =
      0x9020 ! setup starts here SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
      ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
      *
      _start先設(shè)置好目的地址和源地址

      ds:si和es:di

      *
      然后執(zhí)行rep指令

      rep指令是重復(fù)的意思,它以cx寄存器的值為判斷,如果cx的值為0就停止

      *
      movw指令

      開始從[si]處移動cx個字到[di]處,這里也就是一共移動了256個字,512字節(jié)

      *
      最后跳轉(zhuǎn)到0x9000開始執(zhí)行
      _start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub
      si,si sub di,di rep movw jmpi go,INITSEG
      * 現(xiàn)在的這些代碼都是在0x90000后的
      * 先重新設(shè)置段寄存器和棧指針 go: mov ax,cs mov ds,ax mov es,ax ! put stack at 0x9ff00. mov
      ss,ax mov sp,#0xFF00 ! arbitrary value >>512
      *
      這一部分和我之前的一樣,就是調(diào)用中斷來讀取磁盤內(nèi)容,只是Linux讀取的是在第二扇區(qū)的setup模塊

      *
      如果失敗就重新設(shè)置驅(qū)動器然后跳回重新讀取

      *
      成功就跳到ok_load_setup

      *
      ok_load_setup是設(shè)置根文件系統(tǒng)設(shè)備的,并且讀入SYSTEM模塊 (內(nèi)核的主要部分)到0x10000處,結(jié)尾是跳到SETUP模塊
      load_setup: mov dx,#0x0000 ! drive 0, head 0 mov cx,#0x0002 ! sector 2, track
      0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service
      2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue mov
      dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup
      小結(jié)

      一個簡單的boot引導(dǎo)程序,顧名思義就是把做一些引導(dǎo)工作的,進行一些初始化設(shè)置再讀入真正的內(nèi)核部分,進入OS。

      其實Linux 0.12一個完整的boot應(yīng)該還包括setup.s用來完成OS啟動前最后的設(shè)置 (進入保護模式等)
      ,head.s則是進入之后的設(shè)置。但是因為這兩部分包含了一些其它重要概念,所以打算再下一篇寫。

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          成人免费毛片 嘿嘿连载视频… | 天天躁日日躁狠狠躁欧美老牛 | 国产一级片中文字幕 | 国产脚交chinesefootjob | 啪啪高清无码视频 | 我和大乳寡妇在线观看 | 91久久欧美极品XXXXⅩ | 亚洲欧美性爱在线观看 | 俺也来俺也去俺也射 | 大香蕉日韩视频 |